1: \documentclass{bfk2}
2: \usepackage{epsfig}
3: \usepackage{url}
4: \usepackage{mathbbol}
5: \usepackage{booktabs}
6: \usepackage{fancyvrb}
7:
8: % Environment codeblock for cool verbatims using pkg fancyvrb:
9: \newenvironment*{codeblock}%
10: {\Verbatim[fontsize=\small,%
11: numbers=left,%
12: baselinestretch=0.9,%
13: xleftmargin=2em,%
14: numbersep=1em,
15: commandchars=\\\{\}]}
16: {\endVerbatim}
17:
18: \newcommand*{\CC}{C\({}^{{}_{++}}\)} % C++ should be typset prettier.
19:
20: % the date of submission to JSC was \date{27 April 2000}
21: \date{29 January 2001}
22: \title[GiNaC]{Introduction to the GiNaC Framework for Symbolic
23: Computation within the \CC\ Programming Language}
24: \author[C. Bauer, A. Frink, R. Kreckel]%
25: {Christian Bauer, Alexander Frink, Richard Kreckel \\
26: Institute of Physics, Johannes-Gutenberg-University, Mainz, Germany}
27:
28: \begin{document}
29: \maketitle
30: \begin{abstract}
31: The traditional split-up into a low level language and a high level
32: language in the design of computer algebra systems may become
33: obsolete with the advent of more versatile computer languages. We
34: describe GiNaC, a special-purpose system that deliberately denies
35: the need for such a distinction. It is entirely written in \CC\ and
36: the user can interact with it directly in that language. It was
37: designed to provide efficient handling of multivariate polynomials,
38: algebras and special functions that are needed for loop calculations
39: in theoretical quantum field theory. It also bears some potential
40: to become a more general purpose symbolic package.
41: \end{abstract}
42:
43: \section{Introduction}
44:
45: Historically, in the design and implementation of symbolic computation
46: engines, the focus has always been rather on algebraic capabilities
47: than on language design. The need for efficient computation in all
48: fields of science has led to the development of powerful algorithms.
49: Thus, the border line between inexact numerical and exact analytical
50: computation has moved, such that more computation may be done exactly
51: before resorting to numerical methods. This development has had great
52: influence on the working practice in such fields as engineering (e.g.
53: robotics), computer science (e.g. networks), physics (e.g. high
54: energy physics) and even mathematics (from group theory to automatic
55: theorem proving in geometry).
56:
57: This border line between analytical and numerical methods, however,
58: has quite often remained a painful obstacle in the successful
59: application of computer algebra systems (CASs). Usually, some results
60: are obtained with the help of a CAS and later these results are
61: integrated into some other program. This is not only restricted to
62: numerical results, where one frequently translates the output of some
63: CAS to C or even FORTRAN. It is questionable whether the distinction
64: between one language for writing down symbolical algebra and one for
65: obtaining numerical results and maybe a third one for integrating
66: everything in a graphical user interface has any reason other than
67: historical ones. In our experience it frequently leads to confusions;
68: the \verb|xloops| project~\cite{xloops98} has somewhat suffered from
69: this.
70:
71: The chapter ``A Critique of the Mathematical Abilities of CA Systems''
72: in~\cite{CASguide} has a section called ``Mathematics versus Computer
73: Science'' where some misbehaviours of common CASs are shown. There,
74: the first test tries to find out if a global variable is accessed in
75: some local context, in particular within sums, products, limits and
76: integrals. Of the seven systems tested, only Derive passed the test.
77: Even explicitly declaring a variable to be local does not always spare
78: the programmer surprises: MapleV Releases 3 to 5 for instance do not
79: honor local variables if they are created by concatenating strings
80: using the operator dot~({\tt .}), a feature people often feel tempted
81: to use for elegant subscripting. So created variables may be used as
82: lvalues in assigning a {\em local} variable within a procedure but the
83: result is a modified {\em global} variable.\footnote{We have been told
84: that Maple6 still suffers from this problem.} Such violations of
85: scope have repeatedly led to subtle bugs within \verb|xloops|. They
86: are notoriously difficult to disentangle since they go undetected
87: until some other part of the program breaks.
88:
89: The general picture is that most currently used CASs are
90: linguistically rather impoverished and put up high obstacles to the
91: design of combined symbolical/numerical/graphical programs. An
92: incomplete look into the toolchest of a \CC\ developer throws some
93: light on the features that any professional programmer will miss
94: from common CA systems:
95: \begin{itemize}
96: \item[\(\bullet\)] structured data types like \verb|struct|s and
97: \verb|class|es instead of unnamed lists of lists,
98: \item[\(\bullet\)] the object oriented (OO) programming paradigm in
99: general,
100: \item[\(\bullet\)] {\tt template}s, which allow for generic (i.e.
101: type-independent) programming even in a strongly typed language,
102: \item[\(\bullet\)] the Standard Template Library (STL), which provides
103: convenient classes for many kinds of containers with asymptotically
104: ideal access methods and to a large degree container-independent
105: algorithms ({\tt sort}, etc) to be instantiated by the programmer.
106: \item[\(\bullet\)] modularization facilities like {\tt namespace}s,
107: \item[\(\bullet\)] powerful development tools like editors (e.g. with
108: automatic indentation and syntax highlighting), debuggers,
109: visualization tools, documentation generators, etc.,
110: \item[\(\bullet\)] flexible error handling with exceptions,
111: \item[\(\bullet\)] last, but not least: an established standard
112: (\citeauthor{ISO14882}) which guards the programmer from arbitrary
113: changes made by the manufacturer which break existing code.
114: \end{itemize}
115:
116: Solutions for those problems so far are restricted to allowing calls
117: to CAS functionality from other languages and the already mentioned
118: code generators. At most, bridges are built to cross the gap, no
119: unification of the two worlds is achieved.
120:
121: \subsection{The goal}
122:
123: Loop calculations in quantum field theory (QFT) are one example for
124: such a combined symbolical and numerical effort. The \(n\)-fold
125: nested integrals arising there are solved with specialized methods
126: that demand efficient handling of order \(10^3\)-\(10^6\) symbolic
127: terms. At the one-loop level, Feynman graphs can be expressed
128: completely analytically and so in the early 90's our group started to
129: build up the program package \verb|xloops| based on Maple. The
130: continuation of \verb|xloops| with Maple up to the two-loop level
131: turned out to be very difficult to accomplish. There were numerous
132: technical issues of coding such as the ones outlined above as well as
133: a nasty restriction built into MapleV of no more than \(2^{16}\) terms
134: in sums.
135:
136: An analysis of \verb|xloops| showed, however, that only a small part
137: of the capabilities of Maple is actually needed: composition of
138: expressions consisting of symbols and elementary functions,
139: replacement of symbols by expressions, non-commuting objects,
140: arbitrarily sized integers and rationals and arbitrary precision
141: floats, collecting expressions in equal terms, power series expansion,
142: simplification of rational expressions and solutions of symbolic
143: linear equation systems.
144:
145: It is possible to express all this directly in \CC\ if one introduces
146: some special classes of symbols, sums, products, etc. More generally,
147: one wishes to freely pass general expressions to functions and back.
148: Here is an example of how some of these things are actually expressed
149: in \CC\ using the GiNaC\footnote{GiNaC is a recursive acronym for {\em
150: GiNaC is Not a CAS}.} framework:
151: \begin{codeblock}
152: #include <ginac/ginac.h>
153: using namespace GiNaC;
154:
155: ex HermitePoly(const symbol & x, int n)
156: \{
157: const ex HGen = exp(-pow(x,2));
158: \textit{// uses the identity H_n(x) == (-1)^n exp(x^2) (d/dx)^n exp(-x^2)}
159: return normal(pow(-1,n) * HGen.diff(x, n) / HGen);
160: \}
161:
162: int main(int argc, char **argv)
163: \{
164: int degree = atoi(argv[1]);
165: numeric value = numeric(argv[2]);
166: symbol z("z");
167: ex H = HermitePoly(z,degree);
168: cout << "H_" << degree << "(z) == "
169: << H << endl;
170: cout << "H_" << degree << "(" << value << ") == "
171: << H.subs(z==value) << endl;
172: return 0;
173: \}
174: \end{codeblock}
175: When this program is compiled and called with \(11\) and \(0.8\) as
176: command line arguments it will readily print out the 11th Hermite
177: polynomial together with that polynomial evaluated numerically at
178: \(z=0.8\):
179: \begin{codeblock}
180: H_11(z) == -665280*z+2217600*z^3-1774080*z^5+506880*z^7-56320*z^9+2048*z^11
181: H_11(0.8) == 120773.8855954841959
182: \end{codeblock}
183: Alternatively, it may also be called with an exact rational second
184: argument \(4/5\):
185: \begin{codeblock}
186: H_11(z) == -665280*z+2217600*z^3-1774080*z^5+506880*z^7-56320*z^9+2048*z^11
187: H_11(4/5) == 5897162382592/48828125
188: \end{codeblock}
189: It calls the subroutine \verb|HermitePoly| with the symbolic variable
190: \(z\) and the desired order as arguments. There, the Hermite
191: polynomial is computed in a straightforward way using a Rodrigues
192: representation. The \verb|normal()| call therein cancels the
193: generators \verb|HGen| in numerator and denominator. Note that the
194: operators \verb|*| and \verb|/| have been overloaded to allow
195: expressive construction of composite expressions and that both
196: object-style method invocations ({\em obj}\verb|.f(|{\em arg}\verb|)|)
197: as well as function-style calls (\verb|f(|{\em obj}\verb|,|{\em
198: arg}\verb|)|) are possible. Technically, the whole GiNaC library is
199: hidden in a namespace that needs to be imported (for instance with the
200: \verb|using| directive in line 2) in order to allow easy integration
201: with other packages without potential name clashes. This is just a
202: crude example that invites for obvious refinement like parameter
203: checking or rearranging the polynomial in order to make it less
204: sensitive to numerical rounding errors.
205:
206: Since pattern matching is something that doesn't blend very naturally
207: into the context of a declarative language like \CC, GiNaC takes care
208: to use term rewriting systems which bring expressions into equivalent
209: canonical forms as far as feasible in an economic way. In addition,
210: specialized transformations may be invoked by the user, for instance
211: an \verb|.expand()| method for fully expanding polynomials or a
212: \verb|.normal()| method for polynomial GCD cancellation. As for
213: instance in {\sc Form}~\cite{VermaserenForm} the user alone is
214: responsible for deciding the order of steps to take in some
215: application, there are only very few rules built into GiNaC. The only
216: kind of pattern matching we want to allow is an atomic one, where
217: inside an expression a symbol (or a list of symbols) is replaced by
218: other expressions in this fashion: \verb|(5*a).subs(a==b)|
219: \(\Rightarrow\) \verb|5*b|. We believe that such a conservative
220: restriction should be acceptable to programmers of large systems since
221: the potential ambiguities introduced by pattern matching and
222: overlapping rules can be rather subtle.
223:
224:
225: \section{The implementation}
226:
227: The implementation of GiNaC follows an OO philosophy: all algebraic
228: classes that may be manipulated by the system are derived from an
229: abstract base class called \verb|basic|\footnote{Strictly speaking,
230: GiNaC does not have any abstract base classes in the \CC\ sense,
231: since there are defaults for all methods. We therefore define an
232: abstract base class to be one which does not make sense to
233: instantiate.}. Some of the classes are atomic (symbols,
234: numbers\dots), others are container classes (sums, products\dots).
235: Since at run-time container classes must be flexible enough to store
236: different objects whose size must, however, be defined already at
237: compile-time, we define the class of all expressions, simply called
238: \verb|ex|. It is a wrapper class that stands outside the class
239: hierarchy and it contains mainly a pointer to some object of the class
240: hierarchy. The container classes thus may be restricted to hold
241: objects of the wrapper class \verb|ex|
242: (figure~\ref{fig:classhierarchy}).
243: \begin{figure}['t']
244: \epsfig{file=classhierarchy.eps,width=\textwidth}
245: \caption{The GiNaC class hierarchy and some of the relations between the
246: classes.}\label{fig:classhierarchy}
247: \end{figure}
248: Because of this ``handle'' character, objects of class \verb|ex| are also
249: the ones the user creates most of the time. Most operators have been
250: overloaded to work within this class and they are the most common
251: arguments to the functions in GiNaC. Two obvious drawbacks of this
252: flexibility are the lack of type-safety at compile-time and possible
253: performance losses by additional function calls in method invocations.
254: To some extent, this can be remedied by carefully overloading
255: specialized functions and operators. On the other hand, the interplay
256: between \verb|ex| and \verb|basic| (and all classes derived from it)
257: enables us to implement an efficient memory management using reference
258: counting and copy-on-write semantics: multiply occurring expressions
259: (or subexpressions within an expression tree) are shared in memory and
260: copied only when they need to be modified in one part of the program.
261: This happens in a completely transparent way for the user. In order
262: to create one's own classes managed this way it suffices to derive them
263: from class \verb|basic|.
264: \begin{table}['t']
265: %\normalsize
266: \begin{tabular*}{\textwidth}{@{}l@{\extracolsep{\fill}}l@{\extracolsep{\fill}}r@{}}
267: \toprule
268: class & description & examples \\
269: \midrule
270: \verb|symbol| & algebraic symbols & \(x\) \\
271: \verb|numeric| & polymorphic CLN numbers & 42, \(\frac{7}{3}i\), 0.12345678 \\
272: \verb|constant| & symbols with associated \verb|numeric| & \(\pi\) \\
273: \verb|add| & sums of expressions & \(a-2b+3\) \\
274: \verb|mul| & products of expressions & \(2a^2(x\!+\!y\!+\!z)/b\) \\
275: \verb|power| & exponentials & \(x^2\), \(a^{(b+c)}\), \(\sqrt{2}\) \\
276: \verb|pseries| & truncated power series & \(x-\frac{1}{6}x^3+\mathcal{O}(x^5)\) \\
277: \verb|function| & symbolic functions & \(\sin(2x)\) \\
278: \verb|lst| & list of expressions & \verb|[|\(x,2y,3+z\)\verb|]| \\
279: \verb|relational| & relation between two expressions & \(x\)\verb|==|\(y\) \\
280: \verb|matrix| & matrices (and vectors) of expressions & \scriptsize\((\!\begin{array}{cc}1\!&\!x\\-x\!&\!1\end{array}\!)\) \\
281: \verb|ncmul| & container for non-commutative objects & \(\gamma_0\gamma_1\)\\
282: \verb|color|, \verb|coloridx| & \(SU(3)\) Lie algebra element, -index & \(T_a\), \(\delta_{ab}\), \(f_{abc}\) \\
283: \verb|lortensor|, \verb|lorentzidx| & Lorentz tensor, -index & \(p^\mu, g_{\mu\nu} \) \\
284: \bottomrule
285: \end{tabular*}
286: \caption{List of the most important classes from
287: figure~\ref{fig:classhierarchy} and their purpose.}
288: \label{tab:classoverview}
289: \end{table}
290:
291: Table~\ref{tab:classoverview} gives an overview of what classes are
292: currently provided by GiNaC. We are now going to describe some of
293: them.
294:
295: \subsection{Numbers}
296:
297: Arbitrarily sized integers, rationals and arbitrary precision floating
298: point numbers are all stored in the class \verb|numeric|. This is an
299: interface that encapsulates the foundation class \verb|cl_N| of Bruno
300: Haible's \CC\ library {\tt CLN}~\cite{CLN} in a completely transparent
301: way.
302:
303: The choice fell to {\tt CLN} because it provides fast and
304: asymptotically ideal algorithms for all basic operations (Karatsuba
305: and Sch{\"o}nhage-Strassen multiplication) and a very flexible way of
306: dealing with rationals and complex numbers. Also, it does not put any
307: burden of memory management on us since all objects are
308: reference-counted---just like GiNaC's---so there are no interferences
309: with garbage collection. Its polymorphic types are perfectly suited
310: for implementing a CAS, and indeed were written with this intention in
311: mind. For instance, it honors the injection of the naturals into the
312: rationals and of the complex numbers into the reals: Rationals are
313: instantanously and efficiently normalized to coprime integer numerator
314: and denominator and converted to integers if the resulting denominator
315: is unity and complex numbers are instantanously converted to reals if
316: the imaginary part vanishes. Non-exact numbers, i.e. floats and
317: complex floats are constructed with any user-defined accuracy.
318:
319: GiNaC provides functions and operators defined on class \verb|numeric|
320: to the user so the wrapper class \verb|ex| may be circumvented. This
321: provides both some level of type-safety as well as a considerable
322: speedup.
323:
324: \subsection{Symbols and Constants}
325:
326: Symbols are represented by objects of class {\tt symbol}. Thus,
327: construction of symbols is done by statements like {\tt symbol x,y;}.
328: In a compiled language like \CC\ the name of a variable is of course
329: unavailable to the running program. For printing purposes therefore a
330: constructor from a string is provided, i.e. {\tt symbol
331: x("x"),y("y");}. This is reminiscent of Common Lisp's~\cite{CLTL}
332: concept of {\em print name}. The responsibility for not mixing up
333: names (as in {\tt symbol x("y"),y("x");}) is entirely laid on the
334: user. The string is not at all used for identification of objects.
335: If omitted, the system will still deal out a unique string.
336:
337: Unlike in other symbolic system evaluators, expressions may not be
338: assigned to symbols. This is a restriction we had to introduce for
339: the sake of consistency in the non-symbolic language \CC. It is,
340: however, possible to substitute a symbol within an expression with
341: some other expression by calling the {\tt .subs()} method.
342:
343: Objects of class {\tt constant} behave much like symbols except that
344: they must return some specific number (if possible to arbitrary
345: accuracy) when the method {\tt .evalf()} is called. There are several
346: predefined constants like \(\pi\) etc. which have an associated
347: function for numerical evaluation to arbitrary accuracy. Another
348: possibility is an associated fixed precision \verb|numeric|. Thus,
349: physical constants are easily constructed by the user, as in this
350: fragment:
351: \begin{codeblock}
352: constant qe("qe",numeric(1.60219e-19)); \textit{// elementary charge}
353: cout << qe << endl; \textit{// prints 'qe'}
354: cout << evalf(qe) << endl; \textit{// prints '1.60219E-19'}
355: \end{codeblock}
356:
357: \subsection{Polynomial arithmetic: the classes {\tt add}, {\tt mul} and {\tt power}}
358:
359: The main object of interest being efficient multivariate polynomials
360: and rational functions, GiNaC allows the creation of such objects
361: using the overloaded operators \verb|+|, \verb|-|, \verb|*| and
362: \verb|/| and the overloaded function
363: \verb|pow(|\(b\)\verb|,|\(e\)\verb|)| for exponentiation of
364: expressions \(b\) and \(e\).\footnote{It is also possible to overload
365: operator {\tt \char'136} for exponentiation in \CC, but this would
366: lead to trouble since it always has lower precedence than {\tt *}.}
367: When such an object is created, the built-in term rewriting rules of
368: the classes \verb|add| and \verb|mul| are automatically invoked to
369: bring it into a canonical form. Subsequent comparison of such objects
370: is then easy and further supported by hash values. Due to the
371: similarity in the rewriting rules for sums and products the actual
372: implementation is mostly hidden in class \verb|expairseq|, from which
373: \verb|add| and \verb|mul| are derived. The internal representation is
374: an unexpanded distributive one. For performance reasons numerical
375: coefficients in front of monomials in sums and numerical exponents in
376: products are treated separately (as shown in
377: figure~\ref{fig:repmpoly}).
378: \begin{figure}['t']
379: \begin{center}
380: \epsfig{file=repmpoly.eps,width=.5\textwidth}
381: \end{center}
382: \caption{Internal representation of the multivariate rational function $2d^3(4a+5b-3)/e$.}
383: \label{fig:repmpoly}
384: \end{figure}
385: The term rewriting rules for class \verb|power| are restricted to
386: those simplifications that can be done efficiently.
387:
388: GiNaC provides the usual set of operations on multivariate
389: polynomials: determination of degree and coefficients, expansion of
390: products over sums, collection of coefficients of like powers,
391: conversion of rational expressions to a normal form (where numerator
392: and denominator are relatively prime polynomials), decomposition of
393: polynomials into unit part, content, and primitive part, and
394: polynomial GCD and LCM computation. For the latter, GiNaC implements
395: the heuristic polynomial GCD algorithm described
396: in~\cite{LiaoFatemanGCD}, augmented by additional heuristics such as
397: cancelling trivial common factors (e.g. \(x^n\)), eliminating
398: variables that occur only in one polynomial, and special handling of
399: partially factored polynomials. If the heuristic algorithm fails,
400: GiNaC falls back to the subresultant PRS algorithm~\cite{algorithms}.
401: This approach has so far proved successful for the application in
402: \verb|xloops|.
403:
404: \subsection{Power series: the class {\tt pseries}}
405:
406: Expressions may be differentiated with respect to any symbol and also
407: expanded as Taylor series or Laurent series. There is no distinction
408: between those two. Series are internally stored in a truncated power
409: series representation, optionally containing an order term, in a
410: special class {\tt pseries}. This class implements efficient
411: addition, multiplication, and powering (including inversion) of series
412: and can convert the internal representation to an ordinary GiNaC
413: expression (polynomial) as well.
414:
415: A program fragment where the mass increase from special relativity
416: \(\gamma=(1\!-(\frac{v}{c})^2)^{-1/2}\) is first Taylor expanded and
417: then inverted and expanded again illuminates the behaviour and syntax
418: of class \verb|pseries| to some extent:
419: \begin{codeblock}
420: symbol v("v"), c("c");
421: ex gamma = 1/sqrt(1 - pow(v/c,2));
422: ex gamma_nr = gamma.series(v==0, 6);
423: cout << pow(gamma_nr,-2) << endl;
424: cout << pow(gamma_nr,-2).series(v==0, 6) << endl;
425: \end{codeblock}
426: Raising the series \(\gamma_{\!{\mbox{\scriptsize nr}}}\) to the power \(-2\) in
427: line 4 just returns
428: \(\big(1+\frac{1}{2}(\frac{v}{c})^2+\frac{3}{8}(\frac{v}{c})^4+\mathcal{O}(v^6)\big)^{-2}\).
429: Only calling the series method again in line 5 makes the output
430: simplify to \(1-v^2/c^2+\mathcal{O}(v^{6})\).
431:
432: \subsection{Functions}
433:
434: \CC\ functions are not suited for symbolic expressions as arguments.
435: This is so because if the evaluation engine is unable to evaluate the
436: argument one wishes to return the function itself which would lead to
437: an infinite recursion. If \verb|x| is an indeterminate, then
438: \verb|sin(x)| is supposed to return \verb|sin(x)|. In order to achive
439: this behaviour the class \verb|function| is introduced. Each object
440: of this class represents a single function (\verb|sin|,
441: \verb|cos|\dots) and methods for evaluation, differentiation and so on
442: may be attached to it. The \CC\ preprocessor is then used to define
443: wrapper functions that return the corresponding objects of class
444: \verb|function|. This allows us to write functions down in \CC\
445: fashion and obtain the behaviour one knows from usual CASs:
446: \begin{codeblock}
447: symbol x("x"), y("y");
448: ex Do = Pi*(x+y/2);
449: cout << "sin(" << Do << ") -> " << sin(Do) << endl;
450: ex Re = Do.subs(y==1);
451: cout << "sin(" << Re << ") -> " << sin(Re) << endl;
452: ex Mi = Re.subs(x==11);
453: cout << "sin(" << Mi << ") -> " << sin(Mi) << endl;
454: ex Fa = Mi.evalf();
455: cout << "sin(" << Fa << ") -> " << sin(Fa) << endl;
456: \end{codeblock}
457: The above fragment prints:
458: \begin{codeblock}
459: sin(Pi*(x+1/2*y)) -> sin(Pi*(x+1/2*y))
460: sin(Pi*(1/2+x)) -> sin(Pi*(1/2+x))
461: sin(23/2*Pi) -> -1
462: sin(36.128315516282622243) -> -1.0
463: \end{codeblock}
464: A great many functions are already predefined in GiNaC, some of them,
465: however, not yet with the full functionality. For instance, polygamma
466: functions may not yet be evaluated numerically.
467:
468:
469: \section{Benchmarks}
470:
471: Naturally, we want to know how GiNaC performs in comparison with other
472: systems. Therefore we subject it and some other symbolic manipulators
473: to several stress tests on different hardware architectures. All
474: tests concentrate on non-\CC\ arithmetics (arbitrary precision instead
475: of hardware-near \verb|int|, \verb|double|) and symbolic expressions.
476: GiNaC is superior when it comes to algorithms which largely rely on
477: machine-near data types. The first two tests were inspired by typical
478: operation patterns in elementary particle physics where many different
479: symbols and deeply nested functions need to be handled. They are
480: designed to detect flaws in the memory management and the
481: implementation of algorithms for manipulation of large container
482: classes (products, sums\dots). This is done by having a close look at
483: the asymptotic runtime behaviour.
484:
485: The first test (figure~\ref{fig:ginac_gamma}, left) consists of three
486: steps:
487: \begin{enumerate}
488: \item let \(e\) be the expanded sum of \(n\) symbols \(\{a_0,\dots a_{n-1}\}\)
489: squared: \(e\leftarrow(\sum_{i=0}^{n-1} a_i)^2\)
490: \item in \(e\) substitute \(a_0 \leftarrow -\sum_{i=2}^{n-1} a_i\)
491: \item expand \(e\) again, it collapses to \({a_1}^2\).
492: \end{enumerate}
493: The third step is the computationally expensive one. The system has
494: to match terms in a sum of \(\approx 2n^2\) elements and eliminate all
495: but one. The timings are taken on an Alphaserver 8400 with CPUs of
496: type EV5 running at 300MHz under Digital Unix 4. This architecture
497: was chosen specifically in order to give MapleV a chance, which has an
498: internal limitation of \(2^{16}-1\) terms in a sum on any other
499: architecture\footnote{We do not have access to any newer version than
500: MapleVR5. We were informed that the new release Maple6 does not
501: suffer from the \(2^{16}-1\) limitation any longer.}. This turns
502: out to limit the test to \(n<182\). This also forced us to resort to
503: a rather old version of MuPAD because no newer one is available for
504: the Alpha platform. The tests were run until we got bored (which we
505: defined to be 400 seconds). Further continuation also would have
506: required more memory since some systems (particularly MuPAD) were
507: allocating extraordinary amounts of RAM. The slopes of the curves are
508: interesting: Those systems that base their memory management on
509: reference counts exhibit the quadratic scaling one would expect from
510: the nature of the test while systems with a garbage collector (Maple
511: and Reducs) start off faster and saturate earlier.
512:
513: \begin{figure}['t']
514: \epsfig{figure=df.eps,height=.51\textwidth,angle=270}
515: \epsfig{figure=gamma.eps,height=.48\textwidth,angle=270}
516: \caption{Runtimes for a substitute-expand consistency test (left)
517: and for series expansion of $\Gamma(x)|_{x=0}$ (right). The tests
518: are described in the text. The left graph was produced on an
519: Alphaserver 8400, the right one on an Intel P-III.}
520: \label{fig:ginac_gamma}
521: \end{figure}
522:
523: Next, we do a mixed test which besides handling of symbols also
524: involves handling of large rational numbers and evaluation of
525: functions at certain points (figure~\ref{fig:ginac_gamma}, right). We
526: calculate the expansion of the Gamma function around the pole at
527: \(x=0\). The result up to order \(x^2\) is:
528: \begin{displaymath}
529: \Gamma(x) = \frac{1}{x} - \gamma
530: + \Big(\frac{\pi^2}{12}\!+\!\frac{\gamma^2}{2}\Big)x
531: - \Big(\frac{\pi^2\gamma}{12}\!+\!\frac{\gamma^3}{6}\!+\!\frac{\zeta(3)}{3}\Big)x^2 +\dots
532: \end{displaymath}
533: It is not completely clear what other systems are doing internally but
534: GiNaC's implementation is simple and lacks any optimization. It falls
535: back to evaluation of Polygamma functions \(\psi_n(1)\) which in turn
536: requires the evaluation of Riemann's Zeta function if their argument
537: is even and, hence, to Bernoulli numbers. We show two curves for
538: Mathematica, since this system decides to return the result in the
539: form of unevaluated Polygamma functions \(\psi_n(1)\). If one insists
540: on a result comparable with the other systems one is forced to
541: introduce calls to \verb|FunctionExpand[]|, which slows the system
542: down more than an order of magnitude (upper curve). Without
543: \verb|FunctionExpand[]| its performance is only slightly worse than
544: GiNaC's but with a funny excursion at high orders for which we do not
545: have an explanation. It should, however, be mentioned that for
546: Mathematica that ugly result in terms of \(\psi_n(1)\) can under
547: certain circumstances be acceptable since it may be handled further
548: without resorting to \(\zeta\)-functions. This becomes apparent when
549: one tries to evaluate the coefficients in the resulting series
550: numerically. Maple's internal limitation results in the breakdown at
551: order \(n=35\) in this test.
552:
553: \begin{table}['t']
554: \begin{tabular*}{\textwidth}{@{}rlr@{.}lr@{.}lr@{.}lr@{.}lr@{.}l@{}}
555: \toprule
556: \multicolumn{2}{@{}l}{} & \multicolumn{2}{c}{\bf GiNaC} & \multicolumn{2}{c}{\bf MapleV} & \multicolumn{2}{c}{\bf MuPAD} & \multicolumn{2}{c}{\bf Pari-GP} & \multicolumn{2}{c}{\bf Singular} \\
557: \multicolumn{2}{@{}l}{\bf Benchmark} & \multicolumn{2}{c}{\bf 0.7} & \multicolumn{2}{c}{\bf R5} & \multicolumn{2}{c}{\bf 1.4.1} & \multicolumn{2}{c}{\bf 2.0.19{\boldmath\(\beta\)}} & \multicolumn{2}{c}{\bf 1-3-7} \\
558: \midrule
559: A: & divide factorials \(\frac{(1000+i)!}{(900+i)!}\big|_{{}^{i=1}}^{{}_{100}}\) & 0&20 & 6&66 & 1&13 & 0&37 & 19&0 \\
560: B: & \(\sum_{i=1}^{1000}1/i\) & 0&019 & 0&08 & 0&10 & 0&041 & 0&54 \\
561: C: & gcd(big integers) & 0&25 & 10&2 & 3&01 & 1&65 & 0&11 \\
562: D: & \(\sum_{i=1}^{10}iyt^i/(y+it)^i\) & 0&78 & 0&13 & 1&21 & 0&20 & \multicolumn{2}{l}{NA\footnotemark} \\
563: E: & \(\sum_{i=1}^{10}iyt^i/(y+|5-i|t)^i\) & 0&63 & 0&05 & 2&33 & 0&11 & \multicolumn{2}{l}{NA\addtocounter{footnote}{-1}\footnotemark} \\
564: F: & gcd(2-var polys) & 0&08 & 0&08 & 0&21 & 0&057 & 0&13 \\
565: G: & gcd(3-var polys) & 2&50 & 2&89 & 3&31 & 99&5 & 0&38 \\
566: H: & det(rank 80 Hilbert) & 10&0 & 33&5 & 42&5 & 3&97 & \multicolumn{2}{l}{CR} \\
567: I: & invert rank 40 Hilbert & 3&38 & 6&41 & 12&0 & 0&62 & \multicolumn{2}{l}{CR} \\
568: J: & check rank 40 Hilbert & 1&61 & 2&28 & 2&95 & 0&22 & \multicolumn{2}{l}{UN} \\
569: K: & invert rank 70 Hilbert & 22&1 & 92&0 & 74&0 & 5&90 & \multicolumn{2}{l}{CR} \\
570: L: & check rank 70 Hilbert & 9&19 & 21&6 & 14&2 & 1&57 & \multicolumn{2}{l}{UN} \\
571: M\({}_1\): & rank 26 symbolic sparse, det & 0&36 & 0&40 & 0&75 & 0&016 & 0&003 \\
572: M\({}_2\): & rank 101 symbolic sparse, det & 1903&3 & \multicolumn{2}{l}{GU} & \multicolumn{2}{l}{CR} & \multicolumn{2}{l}{CR} & 251&2 \\
573: N: & eval poly at rational functions & \multicolumn{2}{l}{CR} & \multicolumn{2}{l}{GU} & \multicolumn{2}{l}{CR} & \multicolumn{2}{l}{CR} & \multicolumn{2}{l}{NA} \\
574: O\({}_1\): & three rank 15 dets (average) & 43&2 & \multicolumn{2}{l}{GU} & \multicolumn{2}{l}{CR} & \multicolumn{2}{l}{CR} & \multicolumn{2}{l}{CR} \\
575: O\({}_2\): & two GCDs & \multicolumn{2}{l}{CR} & \multicolumn{2}{l}{UN} & \multicolumn{2}{l}{UN} & \multicolumn{2}{l}{UN} & \multicolumn{2}{l}{UN} \\
576: P: & det(rank 101 numeric) & 1&10 & 12&6 & 44&3 & 0&09 & 0&85 \\
577: P': & det(less sparse rank 101) & 6&07 & 13&3 & 46&2 & 0&38 & 1&25 \\
578: Q: & charpoly(P) & 103&9 & 1429&7 & 741&7 & 0&15 & 4&4 \\
579: Q': & charpoly(P') & 212&8 & 1497&3 & 243&1 & \multicolumn{2}{l}{CR} & 5&0 \\
580: \bottomrule
581: \end{tabular*}
582: \caption{Runtimes in seconds for the tests proposed by Lewis and Wester
583: (only as far as applicable to GiNaC) on an Intel P-III 450MHz, 384MB RAM
584: running under Linux. Abbreviations used: GU (gave up), CR (crashed, out
585: of memory), NA (not available), UN (unable, a prerequisite test failed).}
586: \label{tab:lwmark}
587: \end{table}
588:
589: Next, we apply GiNaC to a number of tests invented by R.~Lewis and
590: M.~Wester~\cite{LewisWester}. Strictly speaking, these tests are very
591: much geared towards the particular capabilities of the system Fermat.
592: This explains the abundance of benchmarks on Smith and Hermite normal
593: forms of matrices with numerical entries.
594: Nevertheless, we tried to subject GiNaC to these tests where
595: applicable.\footnote{A fair number of these tests even found their way
596: into the suite of GiNaC's regression tests.} The benchmarks were
597: rerun on the same machine for those systems available to us and the
598: rules of the game were slightly simplified: each system was given the
599: chance to run as long as it needed but it was not allowed to allocate
600: more than physical memory available. The tests involving finite
601: fields and the ones involving Smith and Hermite forms were skipped,
602: since they are not applicable to GiNaC.
603: Tests D and E were slightly rearranged in order to give a meaningful
604: and comparable result: Maple and MuPAD were forced to cancel common
605: factors in the result (using \verb|normal|), something Pari-GP does
606: automatically.
607: The results shown in
608: table~\ref{tab:lwmark} are encouraging but show room for optimization.
609: They also demonstrate some improvement of the other systems (notably
610: Singular) over the original test performed by Lewis and Wester. The
611: reader interested in a detailed description of the tests may
612: consult~\cite{LewisWester}.
613:
614:
615: \section{Conclusions and further work}
616:
617: Although the GiNaC framework was built specifically to become a
618: symbolic engine for complex computations in quantum field theory it is
619: our hope that it turns out to be useful for other applications, too.
620: It provides only modest algebraic knowledge; instead it aims at being
621: a fast and reliable foundation for combined
622: symbolical/numerical/graphical projects in \CC. It may be downloaded
623: and distributed under the terms of the GNU general public license from
624: \url{http://www.ginac.de/}. A tutorial introduction and complete
625: cross references of the source code can also be found there.
626: % obscene TeX-hack for multiple footnotes in table:
627: \addtocounter{footnote}{1}\footnotetext{We were informed that
628: benchmarks D and E can indeed be performed with Singular --- it is
629: just not obvious what the right syntax is.}
630:
631: Because the cycle edit-compile-execute common for all compiled
632: languages may be rather tedious during development, care has been
633: taken in the design of GiNaC to permit an interactive frontend to the
634: library. Currently, there are two such interfaces. The first is the
635: tiny GiNaC interactive shell \verb|ginsh| for quickly manipulating
636: some expressions. It does not provide any programming constructs,
637: only back-reference to the last printed expressions. The second is an
638: interface to the Cint \CC\ interpreter used extensively at CERN in the
639: object-oriented data analysis framework ROOT~\cite{ROOT}.
640:
641: Though at this stage GiNaC is already fully functional for the
642: applications it was originally built for, numerous extensions are
643: imaginable. The web page gives some hints in this direction and
644: further suggestions are more than welcome, as are third-party
645: contributions.
646:
647:
648: \subsection*{Acknowledgement}
649:
650: Part of this work was supported by `Graduiertenkolleg Eichtheorien --
651: Experimentelle Tests und theoretische Grundlagen' at University of
652: Mainz. The authors wish to thank Oliver Welzel for fruitful
653: discussions in the early phase of the project and to Do Hoang Son for
654: extensive testing. Stimulating comments came from Richard Fateman
655: about efficiency in general, Michael Wester about his benchmarks,
656: Stephen Watt about practical experiences with memory management
657: schemes and from Dirk Kreimer and Hubert Spiesberger who contributed
658: considerably by asking tons of good questions.
659:
660: \begin{thebibliography}{}
661:
662: \bibitem[\protect\citeauthoryear{Br{\"u}cher {\em et al.}}{1998}]{xloops98}
663: Br{\"u}cher, L., Franzkowski, J., Kreimer, D. (1998).
664: XLoops: Automated Feynman diagram calculation.
665: {\em Comput. Phys. Commun.\/} {\bf 115}, 140-160.
666:
667: \bibitem[\protect\citeauthoryear{Wester}{1999}]{CASguide}
668: Wester, M., (Editor) (1999)
669: {\em Computer Algebra Systems: A Practical Guide\/}.
670: Chichester, UK: John Wiley \& Sons.
671:
672: \bibitem[\protect\citeauthoryear{ISO/IEC 14882-1998(E)}{1998}]{ISO14882}
673: ISO/IEC 14882-1998(E) (1998).
674: {\em Programming languages---\CC\/}.
675: American National Standards Institute
676:
677: \bibitem[\protect\citeauthoryear{Vermaseren}{1991}]{VermaserenForm}
678: Vermaseren, J.A.M (1991)
679: {\em Symbolic Manipulation with Form, Version 2---Tutorial and Reference Manual\/}.
680: Computer Algebra Nederland, Amsterdam
681:
682: \bibitem[\protect\citeauthoryear{Haible}{2000}]{CLN}
683: Haible, B. (2000)
684: CLN, a Class Library for Numbers.
685: {\em see URL:} \url{http://clisp.cons.org/~haible/packages-cln.html}
686:
687: \bibitem[\protect\citeauthoryear{Steele}{1990}]{CLTL}
688: Steele, G. L. (1990)
689: {\em Common Lisp the Language (2nd ed.)\/}.
690: Woburn, MA: Digital Press.
691:
692: \bibitem[\protect\citeauthoryear{Liao {\em et al.}}{1995}]{LiaoFatemanGCD}
693: Liao, H.-C., Fateman, R. (1995)
694: Evaluation of the Heuristic Polynomial GCD.
695: {\em Proceedings of ISSAC 95\/}, Montreal, ACM Press, 1995,
696: available from URL \url{http://http.cs.berkeley.edu/~fateman/papers/phil8.ps}
697:
698: \bibitem[\protect\citeauthoryear{Geddes {\em et al.}}{1992}]{algorithms}
699: Geddes, K. O., Czapor, S. R., Labahn, G. (1992)
700: {\em Algorithms for Computer Algebra\/}.
701: Kluwer Academic Publishers, Boston
702:
703: \bibitem[\protect\citeauthoryear{Lewis {\em et al.}}{1999}]{LewisWester}
704: Lewis, R. H., Wester, M. (1999)
705: Comparison of Polynomial-Oriented Computer Algebra Systems.
706: {\em SIGSAM Bulletin} {\bf 33/4}, 5-13, available from URL
707: \url{http://www.fordham.edu/lewis/cacomp.html}
708:
709: \bibitem[\protect\citeauthoryear{Brun {\em et al.}}{1996}]{ROOT}
710: Brun, R., Rademakers, F. (1996)
711: ROOT - An Object Oriented Data Analysis Framework
712: {\em Proceedings of AIHENP 97\/}, Laussanne, 1996,
713: available from URL \url{ftp://root.cern.ch/root/laussanne.ps.gz}
714:
715: \end{thebibliography}
716:
717: \end{document}
718: