From f2e7d71e88a82d8f205ce8ca66f51665325585d7 Mon Sep 17 00:00:00 2001 From: Christian Bauer Date: Sat, 27 Nov 1999 17:52:06 +0000 Subject: [PATCH 01/16] - RPM_OPT_FLAGS are used for compiling - added "-k -j $SMP" to the make command line when SMP is available --- GiNaC.spec.in | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/GiNaC.spec.in b/GiNaC.spec.in index 094c3a6e..edd2baa0 100644 --- a/GiNaC.spec.in +++ b/GiNaC.spec.in @@ -28,8 +28,13 @@ numeric applications, graphical interfaces, etc.) under one roof. %setup %build -./configure --prefix=%prefix -make RPM_OPT_FLAGS="$RPM_OPT_FLAGS" +CXXFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%prefix +if [ "$SMP" != "" ]; then + (make "MAKE=make -k -j $SMP"; exit 0) + make +else + make +fi %install rm -rf $RPM_BUILD_ROOT -- 2.44.0 From 15a53d32524bafa5ae5bd36b777591d5f594b0df Mon Sep 17 00:00:00 2001 From: Christian Bauer Date: Sat, 27 Nov 1999 21:28:46 +0000 Subject: [PATCH 02/16] - install-info -> /sbin/install-info --- GiNaC.spec.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GiNaC.spec.in b/GiNaC.spec.in index edd2baa0..e370be64 100644 --- a/GiNaC.spec.in +++ b/GiNaC.spec.in @@ -14,7 +14,7 @@ Source: ftp://ftpthep.physik.uni-mainz.de/pub/GiNaC/GiNaC-%{ver}.tar.gz BuildRoot: /tmp/GiNaC-%{PACKAGE_VERSION}-root Packager: Christian Bauer URL: http://www.ginac.de/ -Prereq: install-info +Prereq: /sbin/install-info Docdir: %{prefix}/doc %description @@ -45,12 +45,12 @@ gzip -9n $RPM_BUILD_ROOT%{prefix}/info/* rm -rf $RPM_BUILD_ROOT %post -p /sbin/ldconfig -install-info %{prefix}/info/ginac.info.gz %{prefix}/info/dir +/sbin/install-info %{prefix}/info/ginac.info.gz %{prefix}/info/dir %postun -p /sbin/ldconfig %preun -install-info --delete %{prefix}/info/ginac.info.gz %{prefix}/info/dir +/sbin/install-info --delete %{prefix}/info/ginac.info.gz %{prefix}/info/dir %files %defattr(-, root, root) -- 2.44.0 From edfa3fd1d662a7d71f223ded9809040f901495f4 Mon Sep 17 00:00:00 2001 From: Christian Bauer Date: Sat, 27 Nov 1999 22:13:58 +0000 Subject: [PATCH 03/16] - tweaked spec file --- GiNaC.spec.in | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/GiNaC.spec.in b/GiNaC.spec.in index e370be64..0a503e88 100644 --- a/GiNaC.spec.in +++ b/GiNaC.spec.in @@ -4,7 +4,7 @@ %define rel 1 %define prefix /usr -Summary: C++ library for symbolic mathematical calculations +Summary: C++ library for symbolic calculations Name: GiNaC Version: %ver Release: %rel @@ -19,10 +19,10 @@ Docdir: %{prefix}/doc %description GiNaC (which stands for "GiNaC is Not a CAS (computer algebra system)") is a -C++ library for symbolic mathematical calculations. It is designed to allow -the creation of integrated systems that embed symbolic manipulations together -with more established areas of computer science (like computation-intense -numeric applications, graphical interfaces, etc.) under one roof. +C++ library for symbolic calculations. It is designed to allow the creation +of integrated systems that embed symbolic manipulations together with more +established areas of computer science (like computation-intense numeric +applications, graphical interfaces, etc.) under one roof. %prep %setup @@ -44,10 +44,12 @@ gzip -9n $RPM_BUILD_ROOT%{prefix}/info/* %clean rm -rf $RPM_BUILD_ROOT -%post -p /sbin/ldconfig +%post +/sbin/ldconfig /sbin/install-info %{prefix}/info/ginac.info.gz %{prefix}/info/dir -%postun -p /sbin/ldconfig +%postun +/sbin/ldconfig %preun /sbin/install-info --delete %{prefix}/info/ginac.info.gz %{prefix}/info/dir @@ -58,7 +60,7 @@ rm -rf $RPM_BUILD_ROOT %{prefix}/lib/lib*.so* %{prefix}/lib/*a %{prefix}/include/* -%{prefix}/info/ginac.info* +%{prefix}/info/* %{prefix}/man/man1/* %{prefix}/share/doc/GiNaC/* %{prefix}/bin/* -- 2.44.0 From 85599ce9c9bbd4aea7ebeca2dbf63b7ad5db27b3 Mon Sep 17 00:00:00 2001 From: Christian Bauer Date: Sat, 27 Nov 1999 23:38:16 +0000 Subject: [PATCH 04/16] - spec file now works --- GiNaC.spec.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GiNaC.spec.in b/GiNaC.spec.in index 0a503e88..5d22b8cf 100644 --- a/GiNaC.spec.in +++ b/GiNaC.spec.in @@ -38,8 +38,8 @@ fi %install rm -rf $RPM_BUILD_ROOT -make prefix=$RPM_BUILD_ROOT%{prefix} install -gzip -9n $RPM_BUILD_ROOT%{prefix}/info/* +make prefix=$RPM_BUILD_ROOT%{prefix} install-strip +gzip -9 $RPM_BUILD_ROOT%{prefix}/info/* %clean rm -rf $RPM_BUILD_ROOT -- 2.44.0 From 726f2a78847ca21d45253306e4499c73ca81f2a6 Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Mon, 29 Nov 1999 16:41:50 +0000 Subject: [PATCH 05/16] - moved the subsections that were marked as 'digression:' to an appendix - corrected the rest of Hubert's list - added a concept index --- doc/tutorial/Makefile.am | 4 +- doc/tutorial/Makefile.in | 4 +- doc/tutorial/ginac.texi | 1356 ++++++++++++++++++++------------------ 3 files changed, 723 insertions(+), 641 deletions(-) diff --git a/doc/tutorial/Makefile.am b/doc/tutorial/Makefile.am index 23edcb64..5eb24799 100644 --- a/doc/tutorial/Makefile.am +++ b/doc/tutorial/Makefile.am @@ -10,8 +10,8 @@ SUFFIXES = .fig .png .eps .txt %.eps: %.fig @if [ "${FIG2DEV}" ]; then \ - echo "Running ${FIG2DEV} -L ps -m 0.8 $< $@..."; \ - ${FIG2DEV} -L ps -m 0.8 $< $@; \ + echo "Running ${FIG2DEV} -L ps -m 0.9 $< $@..."; \ + ${FIG2DEV} -L ps -m 0.9 $< $@; \ else \ echo "warning: fig2dev was not found by configure"; \ fi diff --git a/doc/tutorial/Makefile.in b/doc/tutorial/Makefile.in index a1bcb6b9..8c17b366 100644 --- a/doc/tutorial/Makefile.in +++ b/doc/tutorial/Makefile.in @@ -392,8 +392,8 @@ maintainer-clean-generic clean mostlyclean distclean maintainer-clean %.eps: %.fig @if [ "${FIG2DEV}" ]; then \ - echo "Running ${FIG2DEV} -L ps -m 0.8 $< $@..."; \ - ${FIG2DEV} -L ps -m 0.8 $< $@; \ + echo "Running ${FIG2DEV} -L ps -m 0.9 $< $@..."; \ + ${FIG2DEV} -L ps -m 0.9 $< $@; \ else \ echo "warning: fig2dev was not found by configure"; \ fi diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi index b7ac73ad..2e307ba0 100644 --- a/doc/tutorial/ginac.texi +++ b/doc/tutorial/ginac.texi @@ -2,8 +2,15 @@ @c %**start of header @setfilename ginac.info @settitle GiNaC, an open framework for symbolic computation within the C++ programming language -@setchapternewpage off +@setchapternewpage on @afourpaper +@c For `info' only. +@paragraphindent 0 +@c For TeX only. +@iftex +@c I hate putting "@noindent" in front of every paragraph. +@parindent=0pt +@end iftex @c %**end of header @include version.texi @@ -13,8 +20,8 @@ @end direntry @ifinfo -This file documents GiNaC @value{VERSION}, an open framework for symbolic -computation within the C++ programming language. +This is a tutorial that documents GiNaC @value{VERSION}, an open +framework for symbolic computation within the C++ programming language. Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany @@ -34,12 +41,14 @@ resulting derived work is distributed under the terms of a permission notice identical to this one. @end ifinfo +@finalout +@c finalout prevents ugly black rectangles on overfull hbox lines @titlepage @title GiNaC @value{VERSION} @subtitle An open framework for symbolic computation within the C++ programming language @subtitle @value{UPDATED} @author The GiNaC Group: -@author Christian Bauer, Alexander Frink, Richard B. Kreckel +@author Christian Bauer, Alexander Frink, Richard Kreckel @page @vskip 0pt plus 1filll @@ -65,8 +74,8 @@ notice identical to this one. @c node-name, next, previous, up @top GiNaC -This file documents GiNaC @value{VERSION}, an open framework for symbolic -computation within the C++ programming language. +This is a tutorial that documents GiNaC @value{VERSION}, an open +framework for symbolic computation within the C++ programming language. @menu * Introduction:: GiNaC's purpose. @@ -76,6 +85,7 @@ computation within the C++ programming language. * Important Algorithms:: Algorithms for symbolic manipulations. * Extending GiNaC:: How to extend the library. * A Comparison With Other CAS:: Compares GiNaC to traditional CAS. +* Internal Structures:: Description of some internal structures. * Bibliography:: * Concept Index:: @end menu @@ -84,28 +94,41 @@ computation within the C++ programming language. @node Introduction, A Tour of GiNaC, Top, Top @c node-name, next, previous, up @chapter Introduction +@cindex history of GiNaC The motivation behind GiNaC derives from the observation that most present day computer algebra systems (CAS) are linguistically and -semantically impoverished. It is an attempt to overcome the current -situation by extending a well established and standardized computer -language (C++) by some fundamental symbolic capabilities, thus -allowing for integrated systems that embed symbolic manipulations -together with more established areas of computer science (like -computation-intense numeric applications, graphical interfaces, etc.) -under one roof. - -This tutorial is intended for the novice user who is new to -GiNaC but already has some background in C++ programming. However, -since a hand-made documentation like this one is difficult to keep in -sync with the development the actual documentation is inside the -sources in the form of comments. That documentation may be parsed by -one of the many Javadoc-like documentation systems. If you fail at -generating it you may access it from -@uref{http://www.ginac.de/reference/, the GiNaC home page}. -It is an invaluable resource not only for the advanced user who wishes -to extend the system (or chase bugs) but for everybody who wants to -comprehend the inner workings of GiNaC. This little tutorial on the +semantically impoverished. Although they are quite powerful tools for +learning math and solving particular problems they lack modern +linguistical structures that allow for the creation of large-scale +projects. GiNaC is an attempt to overcome this situation by extending a +well established and standardized computer language (C++) by some +fundamental symbolic capabilities, thus allowing for integrated systems +that embed symbolic manipulations together with more established areas +of computer science (like computation-intense numeric applications, +graphical interfaces, etc.) under one roof. + +The particular problem that led to the writing of the GiNaC framework is +still a very active field of research, namely the calculation of higher +order corrections to elementary particle interactions. There, +theoretical physicists are interested in matching present day theories +against experiments taking place at particle accelerators. The +computations involved are so complex they call for a combined symbolical +and numerical approach. This turned out to be quite difficult to +accomplish with the present day CAS we have worked with so far and so we +tried to fill the gap by writing GiNaC. But of course its applications +are in no way restricted to theoretical physics. + +This tutorial is intended for the novice user who is new to GiNaC but +already has some background in C++ programming. However, since a +hand-made documentation like this one is difficult to keep in sync with +the development, the actual documentation is inside the sources in the +form of comments. That documentation may be parsed by one of the many +Javadoc-like documentation systems. If you fail at generating it you +may access it from @uref{http://www.ginac.de/reference/, the GiNaC home +page}. It is an invaluable resource not only for the advanced user who +wishes to extend the system (or chase bugs) but for everybody who wants +to comprehend the inner workings of GiNaC. This little tutorial on the other hand only covers the basic things that are unlikely to change in the near future. @@ -151,10 +174,9 @@ leaves many open questions. The GiNaC open framework for symbolic computation within the C++ programming language does not try to define a language of it's own as conventional CAS do. Instead, it extends the capabilities of C++ by symbolic -manipulations. Here is how to generate and print a simple (and +manipulations. Here is how to generate and print a simple (and rather pointless) bivariate polynomial with some large coefficients: -@subheading My first GiNaC program (a bivariate polynomial) @example #include using namespace GiNaC; @@ -181,10 +203,10 @@ $ ./hello 355687428096000*x*y+20922789888000*y^2+6402373705728000*x^2 @end example +@cindex Hermite polynomial Next, there is a more meaningful C++ program that calls a function which generates Hermite polynomials in a specified free variable. -@subheading My second GiNaC program (Hermite polynomials) @example #include using namespace GiNaC; @@ -218,18 +240,19 @@ H_4(z) == -48*z^2+16*z^4+12 H_5(z) == 120*z-160*z^3+32*z^5 @end example -This method of generating the coefficients is of course far from -optimal for production purposes. +This method of generating the coefficients is of course far from optimal +for production purposes. -In order to show some more examples of what GiNaC can do we -will now use @command{ginsh}, a simple GiNaC interactive -shell that provides a convenient window into GiNaC's capabilities. +In order to show some more examples of what GiNaC can do we will now use +the @command{ginsh}, a simple GiNaC interactive shell that provides a +convenient window into GiNaC's capabilities. @node What it can do for you, Installation, How to use it from within C++, A Tour of GiNaC @c node-name, next, previous, up @section What it can do for you +@cindex @code{ginsh} After invoking @command{ginsh} one can test and 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 @@ -238,9 +261,9 @@ accompanied man page. Suffice to say that assignments and comparisons in @command{ginsh} are written as they are in C, i.e. @code{=} assigns and @code{==} compares. -It can manipulate arbitrary precision integers in a very fast -way. Rational numbers are automatically converted to fractions of -coprime integers: +It can manipulate arbitrary precision integers in a very fast way. +Rational numbers are automatically converted to fractions of coprime +integers: @example > x=3^150; @@ -365,6 +388,7 @@ units to the metric system is therefore easy: @c node-name, next, previous, up @chapter Installation +@cindex CLN GiNaC's installation follows the spirit of most GNU software. It is easily installed on your system by three steps: configuration, build, installation. @@ -400,17 +424,18 @@ it will refuse to continue. @node Configuration, Building GiNaC, Prerequisites, Installation @c node-name, next, previous, up @section Configuration +@cindex configuration +@cindex Autoconf To configure GiNaC means to prepare the source distribution for -building. It is done via a shell script called @command{configure} -that is shipped with the sources. (Actually, this script is by itself -created with GNU Autoconf from the files @file{configure.in} and -@file{aclocal.m4}.) Since a configure script generated by -GNU Autoconf never prompts, all customization must be done either via -command line parameters or environment variables. It accepts a list -of parameters, the complete set of which can be listed by calling it -with the @option{--help} option. The most important ones will be -shortly described in what follows: +building. It is done via a shell script called @command{configure} that +is shipped with the sources and was originally generated by GNU +Autoconf. Since a configure script generated by GNU Autoconf never +prompts, all customization must be done either via command line +parameters or environment variables. It accepts a list of parameters, +the complete set of which can be listed by calling it with the +@option{--help} option. The most important ones will be shortly +described in what follows: @itemize @bullet @@ -464,24 +489,23 @@ examples. (Substitute @command{setenv @var{VARIABLE} @var{value}} for @command{export @var{VARIABLE}=@var{value}} if the Berkeley C shell is your login shell.) -@subheading Sample sessions of how to call the configure script - -Simple configuration for a site-wide GiNaC library assuming everything -is in default paths: +Here is a simple configuration for a site-wide GiNaC library assuming +everything is in default paths: @example $ export CXXFLAGS="-Wall -O2" $ ./configure @end example -Configuration for a private static GiNaC library with several components -sitting in custom places (site-wide @acronym{GCC} and private @acronym{CLN}), -the compiler pursuaded to be picky and full assertions switched on: +And here is a configuration for a private static GiNaC library with +several components sitting in custom places (site-wide @acronym{GCC} and +private @acronym{CLN}). The compiler is pursuaded to be picky and full +assertions and debugging are switched on: @example $ export CXX=/usr/local/gnu/bin/c++ $ export CPPFLAGS="$(CPPFLAGS) -I$(HOME)/include" -$ export CXXFLAGS="$(CXXFLAGS) -DDO_GINAC_ASSERT -ggdb -Wall -ansi -pedantic -O2" +$ export CXXFLAGS="$(CXXFLAGS) -DDO_GINAC_ASSERT -ggdb -Wall -ansi -pedantic" $ export LDFLAGS="$(LDFLAGS) -L$(HOME)/lib" $ ./configure --disable-shared --prefix=$(HOME) @end example @@ -490,15 +514,17 @@ $ ./configure --disable-shared --prefix=$(HOME) @node Building GiNaC, Installing GiNaC, Configuration, Installation @c node-name, next, previous, up @section Building GiNaC +@cindex building GiNaC After proper configuration you should just build the whole library by typing - @example $ make @end example - -at the command prompt and go for a cup of coffee. +at the command prompt and go for a cup of coffee. The exact time it +takes to compile GiNaC depends not only on the speed of your machines +but also on other parameters, for instance what value for @env{CXXFLAGS} +you entered. Optimization may be very time-consuming. Just to make sure GiNaC works properly you may run a simple test suite by typing @@ -511,15 +537,21 @@ This will compile some sample programs, run them and compare the output to reference output. Each of the checks should return a message @samp{passed} together with the CPU time used for that particular test. If it does 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 +if something was broken during the development, not a sanity check of your system. Another intent is to allow people to fiddle around with optimization. If @acronym{CLN} was installed all right this step is unlikely to return any errors. +Generally, the top-level Makefile runs recursively to the +subdirectories. It is therfore safe to go into any subdirectory +(@code{doc/}, @code{ginsh/}, ...) and simply type @code{make} +@var{target} there in case something went wrong. + @node Installing GiNaC, Basic Concepts, Building GiNaC, Installation @c node-name, next, previous, up @section Installing GiNaC +@cindex installation To install GiNaC on your system, simply type @@ -527,9 +559,9 @@ To install GiNaC on your system, simply type $ make install @end example -As described in the section about configuration -the files will be installed in the following directories (the -directories will be created if they don't already exist): +As described in the section about configuration the files will be +installed in the following directories (the directories will be created +if they don't already exist): @itemize @bullet @@ -546,34 +578,36 @@ All the header files will be installed into @file{@var{PREFIX}/include/ginac/} @item All documentation (HTML and Postscript) will be stuffed into -@file{@var{PREFIX}/share/doc/GiNaC/} (or @file{@var{DATADIR}/doc/GiNaC/}, if -specified). +@file{@var{PREFIX}/share/doc/GiNaC/} (or +@file{@var{DATADIR}/doc/GiNaC/}, if @var{DATADIR} was specified). @end itemize -Just for the record we will list some other useful make targets: -@command{make clean} deletes all files generated by @command{make}, -i.e. all the object files. In addition @command{make distclean} -removes all files generated by the configuration. And finally -@command{make uninstall} removes the installed library and header -files@footnote{Uninstallation does not work after you have called -@command{make distclean} since the @file{Makefile} is itself generated -by the configuration from @file{Makefile.in} and hence deleted by -@command{make distclean}. There are two obvious ways out of this -dilemma. First, you can run the configuration again with the same -@var{PREFIX} thus creating a @file{Makefile} with a working -@samp{uninstall} target. Second, you can do it by hand since you -now know where all the files went during installation.}. +For the sake of completeness we will list some other useful make +targets: @command{make clean} deletes all files generated by +@command{make}, i.e. all the object files. In addition @command{make +distclean} removes all files generated by the configuration and +@command{make maintainer-clean} goes one step further and deletes files +that may require special tools to rebuild (like the @command{libtool} +for instance). Finally @command{make uninstall} removes the installed +library, header files and documentation@footnote{Uninstallation does not +work after you have called @command{make distclean} since the +@file{Makefile} is itself generated by the configuration from +@file{Makefile.in} and hence deleted by @command{make distclean}. There +are two obvious ways out of this dilemma. First, you can run the +configuration again with the same @var{PREFIX} thus creating a +@file{Makefile} with a working @samp{uninstall} target. Second, you can +do it by hand since you now know where all the files went during +installation.}. @node Basic Concepts, Expressions, Installing GiNaC, Top @c node-name, next, previous, up @chapter Basic Concepts -This chapter will describe the different fundamental objects -that can be handled by GiNaC. But before doing so, it is worthwhile -introducing you to the more commonly used class of expressions, -representing a flexible meta-class for storing all mathematical -objects. +This chapter will describe the different fundamental objects that can be +handled by GiNaC. But before doing so, it is worthwhile introducing you +to the more commonly used class of expressions, representing a flexible +meta-class for storing all mathematical objects. @menu * Expressions:: The fundamental GiNaC class. @@ -581,7 +615,7 @@ objects. * Symbols:: Symbolic objects. * Numbers:: Numerical objects. * Constants:: Pre-defined constants. -* Fundamental operations:: The power, add and mul classes +* Fundamental operations:: The power, add and mul classes. * Built-in functions:: Mathematical functions. @end menu @@ -589,15 +623,15 @@ objects. @node Expressions, The Class Hierarchy, Basic Concepts, Basic Concepts @c node-name, next, previous, up @section Expressions +@cindex expression (class @code{ex}) +@cindex @code{has()} -The most common class of objects a user deals with is the -expression @code{ex}, representing a mathematical object -like a variable, number, function, sum, product, etc... Expressions -may be put together to form new expressions, passed as arguments to -functions, and so on. Here is a little collection of valid -expressions: +The most common class of objects a user deals with is the expression +@code{ex}, representing a mathematical object like a variable, number, +function, sum, product, etc... Expressions may be put together to form +new expressions, passed as arguments to functions, and so on. Here is a +little collection of valid expressions: -@subheading Examples of expressions @example ex MyEx1 = 5; // simple number ex MyEx2 = x + 2*y; // polynomial in x and y @@ -606,94 +640,18 @@ ex MyEx4 = sin(x + 2*y) + 3*z + 41; // containing a function ex MyEx5 = MyEx4 + 1; // similar to above @end example -Before describing the more fundamental objects that form the building -blocks of expressions we'll have a quick look under the hood by -describing how expressions are internally managed. - -@unnumberedsubsec Digression: Expressions are reference counted - -An expression is extremely light-weight since internally it -works like a handle to the actual representation and really holds -nothing more than a pointer to some other object. What this means in -practice is that whenever you create two @code{ex} and set -the second equal to the first no copying process is involved. Instead, -the copying takes place as soon as you try to change the second. -Consider the simple sequence of code: +Expressions are handles to other more fundamental objects, that many +times contain other expressions thus creating a tree of expressions +(@xref{Internal Structures} for particular examples). Most methods on +@code{ex} therefore run top-down through such an expression tree. For +example, the method @code{has()} scans recursively for occurrences of +something inside an expression. Thus, if you have declared @code{MyEx4} +as in the example above @code{MyEx4.has(y)} will find @code{y} inside +the argument of @code{sin} and hence return @code{true}. -@subheading Simple copy-on-write semantics -@example -#include -using namespace GiNaC; - -int main() -@{ - symbol x("x"), y("y"), z("z"); - ex e1, e2; - - e1 = sin(x + 2*y) + 3*z + 41; - e2 = e1; // e2 points to same object as e1 - cout << e2 << endl; // prints sin(x+2*y)+3*z+41 - e2 += 1; // e2 is copied into a new object - cout << e2 << endl; // prints sin(x+2*y)+3*z+42 - // ... -@} -@end example - -The line @code{e2 = e1;} creates a second expression pointing to the -object held already by @code{e1}. The time involved for this operation -is therefore constant, no matter how large @code{e1} was. Actual -copying, however, must take place in the line @code{e2 += 1;} because -@code{e1} and @code{e2} are not handles for the same object any more. -This concept is called @dfn{copy-on-write semantics}. It increases -performance considerably whenever one object occurs multiple times and -represents a simple garbage collection scheme because when an @code{ex} -runs out of scope its destructor checks whether other expressions handle -the object it points to too and deletes the object from memory if that -turns out not to be the case. A slightly less trivial example of -differentiation using the chain-rule should make clear how powerful this -can be. - -@subheading Advanced copy-on-write semantics -@example -#include -using namespace GiNaC; - -int main() -@{ - symbol x("x"), y("y"); - - ex e1 = x + 3*y; - ex e2 = pow(e1, 3); - ex e3 = diff(sin(e2), x); // first derivative of sin(e2) by x - cout << e1 << endl // prints x+3*y - << e2 << endl // prints (x+3*y)^3 - << e3 << endl; // prints 3*(x+3*y)^2*cos((x+3*y)^3) - // ... -@} -@end example - -Here, @code{e1} will actually be referenced three times while @code{e2} -will be referenced two times. When the power of an expression is built, -that expression needs not be copied. Likewise, since the derivative of a -power of an expression can be easily expressed in terms of that expression, -no copying of @code{e1} is involved when @code{e3} is constructed. So, -when @code{e3} is constructed it will print as -@code{3*(x+3*y)^2*cos((x+3*y)^3)} but the argument of @code{cos()} only -holds a reference to @code{e2} and the factor in front is just @code{3*e1^2}. - -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. If you still have an uncertain feeling with -copy-on-write semantics, we recommend you have a look at the -@uref{http://www.cerfnet.com/~mpcline/c++-faq-lite/, C++-FAQ lite} by -Marshall Cline. Chapter 16 covers this issue and presents an -implementation which is pretty close to the one in GiNaC. - -So much for expressions. But what exactly are these expressions -handles of? This will be answered in the following sections. +The next sections will outline the general picture of GiNaC's class +hierarchy and describe the classes of objects that are handled by +@code{ex}. @node The Class Hierarchy, Symbols, Expressions, Basic Concepts @@ -701,155 +659,102 @@ handles of? This will be answered in the following sections. @section The Class Hierarchy GiNaC's class hierarchy consists of several classes representing -mathematical objects, all of which (except for @code{ex} -and some helpers) are internally derived from one abstract base class -called @code{basic}. You do not have to deal with objects -of class @code{basic}, instead you'll be dealing with -symbols and functions of symbols. You'll soon learn in this chapter -how many of the functions on symbols are really classes. This is -because simple symbolic arithmetic is not supported by languages like -C++ so in a certain way GiNaC has to implement its own arithmetic. - -To give an idea about what kinds of symbolic composits may be -built we have a look at the most important classes in the class -hierarchy. The dashed line symbolizes a "points to" or "handles" -relationship while the solid lines stand for "inherits from" -relationships. - -@subheading The GiNaC class hierarchy +mathematical objects, all of which (except for @code{ex} and some +helpers) are internally derived from one abstract base class called +@code{basic}. You do not have to deal with objects of class +@code{basic}, instead you'll be dealing with symbols and functions of +symbols. You'll soon learn in this chapter how many of the functions on +symbols are really classes. This is because simple symbolic arithmetic +is not supported by languages like C++ so in a certain way GiNaC has to +implement its own arithmetic. + +To give an idea about what kinds of symbolic composits may be built we +have a look at the most important classes in the class hierarchy. The +dashed line symbolizes a "points to" or "handles" relationship while the +solid lines stand for "inherits from" relationship in the class +hierarchy: + @image{classhierarchy} Some of the classes shown here (the ones sitting in white boxes) are -abstract base classes that are of no interest at all for the user. -They are used internally in order to avoid code duplication if -two or more classes derived from them share certain features. An -example would be @code{expairseq}, which is a container -for a sequence of pairs each consisting of one expression and a number -(@code{numeric}). What @emph{is} visible to the user are the derived -classes @code{add} and @code{mul}, representing sums of terms and products, -respectively. We'll come back later to some more details about these -two classes and motivate the use of pairs in sums and products here. - -@unnumberedsubsec Digression: Internal representation of products and sums - -Although it should be completely transparent for the user of -GiNaC a short discussion of this topic helps to understand the sources -and also explain performance to a large degree. Consider the symbolic -expression @math{2*d^3*(4*a+5*b-3)} which could naively be represented -by a tree of linear containers for addition and multiplication, one -container for exponentiation with base and exponent and some atomic -leaves of symbols and numbers in this fashion: - -@subheading Naive internal representation-tree for @math{2*d^3*(4*a+5*b-3)} -@image{repnaive} - -However, doing so results in a rather deeply nested tree which will -quickly become inefficient to manipulate. If we represent the sum -instead as a sequence of terms, each having a purely numeric -multiplicative coefficient and the multiplication as a sequence of -terms, each having a numeric exponent, the tree becomes much more -flat. - -@subheading Pair-wise internal representation-tree for @math{2*d^3*(4*a+5*b-3)} -@image{reppair} - -The number @code{3} above the symbol @code{d} shows that @code{mul} -objects are treated similarly where the coefficients are interpreted as -@emph{exponents} now. Addition of sums of terms or multiplication of -products with numerical exponents can be coded to be very efficient with -such a pair-representation. Internally, this handling is done by many CAS in -this way. It typically speeds up manipulations by an order of -magnitude. The overall multiplicative factor @code{2} and -the additive term @code{-3} look somewhat cumbersome in -this representation, however, since they are still carrying a trivial -exponent and multiplicative factor @code{1} respectively. -Within GiNaC, this is avoided by adding a field that carries overall -numeric coefficient. - -@subheading Realistic picture of GiNaC's representation-tree for @math{2*d^3*(4*a+5*b-3)} -@image{repreal} - -This also allows for a better handling of numeric radicals, since -@code{sqrt(2)} can now be carried along calculations. Now it should be -clear, why both classes @code{add} and @code{mul} are derived from the -same abstract class: the data representation is the same, only the -semantics differs. In the class hierarchy, methods for polynomial -expansion and the like are reimplemented for @code{add} and @code{mul}, -but the data structure is inherited from @code{expairseq}. +abstract base classes that are of no interest at all for the user. They +are used internally in order to avoid code duplication if two or more +classes derived from them share certain features. An example would be +@code{expairseq}, which is a container for a sequence of pairs each +consisting of one expression and a number (@code{numeric}). What +@emph{is} visible to the user are the derived classes @code{add} and +@code{mul}, representing sums of terms and products, respectively. +We'll come back later to some more details about these two classes and +motivate the use of pairs in sums and products here. @node Symbols, Numbers, The Class Hierarchy, Basic Concepts @c node-name, next, previous, up @section Symbols - -Symbols are for symbolic manipulation what atoms are for -chemistry. You can declare objects of class @code{symbol} -as any other object simply by saying @code{symbol x,y;}. -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 -@code{symbol x("x");}. 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. - -This implies that the strings passed to symbols at construction -time may not be used for comparing two of them. It is perfectly -legitimate to write @code{symbol x("x"),y("x");} but it is -likely to lead into trouble. Here, @code{x} and -@code{y} are different symbols and statements like -@code{x-y} will not be simplified to zero although the -output @code{x-x} looks funny. Such output may also occur -when there are two different symbols in two scopes, for instance when -you call a function that declares a symbol with a name already -existent in a symbol in the calling function. Again, comparing them -(using @code{operator==} for instance) will always reveal -their difference. Watch out, please. - -Although symbols can be assigned expressions for internal -reasons, you should not do it (and we are not going to tell you how it -is done). If you want to replace a symbol with something else in an -expression, you can use the expression's @code{.subs()} -method. +@cindex Symbols (class @code{symbol}) + +Symbols are for symbolic manipulation what atoms are for chemistry. You +can declare objects of class @code{symbol} as any other object simply by +saying @code{symbol x,y;}. 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 @code{symbol x("x");}. 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. + +This implies that the strings passed to symbols at construction time may +not be used for comparing two of them. It is perfectly legitimate to +write @code{symbol x("x"),y("x");} but it is likely to lead into +trouble. Here, @code{x} and @code{y} are different symbols and +statements like @code{x-y} will not be simplified to zero although the +output @code{x-x} looks funny. Such output may also occur when there +are two different symbols in two scopes, for instance when you call a +function that declares a symbol with a name already existent in a symbol +in the calling function. Again, comparing them (using @code{operator==} +for instance) will always reveal their difference. Watch out, please. + +Although symbols can be assigned expressions for internal reasons, you +should not do it (and we are not going to tell you how it is done). If +you want to replace a symbol with something else in an expression, you +can use the expression's @code{.subs()} method. @node Numbers, Constants, Symbols, Basic Concepts @c node-name, next, previous, up @section Numbers +@cindex numbers (class @code{numeric}) +@cindex CLN For storing numerical things, GiNaC uses Bruno Haible's library -@acronym{CLN}. The classes therein serve as foundation -classes for GiNaC. @acronym{CLN} stands for Class Library -for Numbers or alternatively for Common Lisp Numbers. In order to -find out more about @acronym{CLN}'s internals the reader is -refered to the documentation of that library. @inforef{Introduction, , cln}, -for more information. Suffice to say that it -is by itself build on top of another library, the GNU Multiple -Precision library @acronym{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. @acronym{CLN} extends -@acronym{GMP} by several useful things: First, it introduces -the complex number field over either reals (i.e. floating point -numbers with arbitrary precision) or rationals. Second, it -automatically converts rationals to integers if the denominator is -unity and complex numbers to real numbers if the imaginary part -vanishes and also correctly treats algebraic functions. Third it -provides good implementations of state-of-the-art algorithms for all -trigonometric and hyperbolic functions as well as for calculation of -some useful constants. - -The user can construct an object of class @code{numeric} in several ways. -The following example 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. - -@subheading Construction of numbers +@acronym{CLN}. The classes therein serve as foundation classes for +GiNaC. @acronym{CLN} stands for Class Library for Numbers or +alternatively for Common Lisp Numbers. In order to find out more about +@acronym{CLN}'s internals the reader is refered to the documentation of +that library. @inforef{Introduction, , cln}, for more +information. Suffice to say that it is by itself build on top of another +library, the GNU Multiple Precision library @acronym{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. @acronym{CLN} extends +@acronym{GMP} by several useful things: First, it introduces the complex +number field over either reals (i.e. floating point numbers with +arbitrary precision) or rationals. Second, it automatically converts +rationals to integers if the denominator is unity and complex numbers to +real numbers if the imaginary part vanishes and also correctly treats +algebraic functions. Third it provides good implementations of +state-of-the-art algorithms for all trigonometric and hyperbolic +functions as well as for calculation of some useful constants. + +The user can construct an object of class @code{numeric} in several +ways. The following example shows the four most important constructors. +It uses construction from C-integer, construction of fractions from two +integers, construction from C-float and construction from a string: + @example #include using namespace GiNaC; @@ -870,31 +775,34 @@ Note that all those constructors are @emph{explicit} which means you are not allowed to write @code{numeric two=2;}. This is because the basic objects to be handled by GiNaC are the expressions @code{ex} and we want to keep things simple and wish objects like @code{pow(x,2)} to be -handled the same way as @code{pow(x,a)}, which means that we need to allow -a general @code{ex} 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. +handled the same way as @code{pow(x,a)}, which means that we need to +allow a general @code{ex} 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. It may be tempting to construct numbers writing @code{numeric r(3/2)}. This would, however, call C's built-in operator @code{/} for integers -first and result in a numeric holding a plain integer 1. @strong{Never use -@code{/} on integers!} Use the constructor from two integers instead, as -shown in the example above. Writing @code{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 -about dynamically created exact numbers, since their "exactness" -always determines how they ought to be handled. The situation is -different for floating point numbers. Their accuracy is handled by -one @emph{global} variable, called @code{Digits}. (For those readers -who know about Maple: it behaves very much like Maple's @code{Digits}). -All objects of class numeric that are constructed from then on will be -stored with a precision matching that number of decimal digits: - -@subheading Controlling the precision of floating point numbers +first and result in a numeric holding a plain integer 1. @strong{Never +use @code{/} on integers!} Use the constructor from two integers +instead, as shown in the example above. Writing @code{numeric(1)/2} may +look funny but works also. + +@cindex @code{Digits} +@cindex accuracy +We have seen now the distinction between exact numbers and floating +point numbers. Clearly, the user should never have to worry about +dynamically created exact numbers, since their "exactness" always +determines how they ought to be handled, i.e. how "long" they are. The +situation is different for floating point numbers. Their accuracy is +controlled by one @emph{global} variable, called @code{Digits}. (For +those readers who know about Maple: it behaves very much like Maple's +@code{Digits}). All objects of class numeric that are constructed from +then on will be stored with a precision matching that number of decimal +digits: + @example #include using namespace GiNaC; @@ -935,17 +843,16 @@ one deals with most of the time are the polymorphic expressions @code{ex}. @subsection Tests on numbers -Once you have declared some numbers, assigned them to -expressions and done some arithmetic with them it is frequently -desired to retrieve some kind of information from them like asking -whether that number is integer, rational, real or complex. For those -cases GiNaC provides several useful methods. (Internally, they fall -back to invocations of certain CLN functions.) +Once you have declared some numbers, assigned them to expressions and +done some arithmetic with them it is frequently desired to retrieve some +kind of information from them like asking whether that number is +integer, rational, real or complex. For those cases GiNaC provides +several useful methods. (Internally, they fall back to invocations of +certain CLN functions.) -As an example, let's construct some rational number, multiply it -with some multiple of its denominator and check what comes out: +As an example, let's construct some rational number, multiply it with +some multiple of its denominator and test what comes out: -@subheading Sample test on objects of type numeric @example #include using namespace GiNaC; @@ -967,22 +874,21 @@ int main() @} @end example -Note that the variable @code{answer} is constructed here -as an integer by @code{numeric}'s copy constructor but in -an intermediate step it holds a rational number 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 -@acronym{CLN} is responsible for this behaviour and we refer -the reader to @acronym{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. +Note that the variable @code{answer} is constructed here as an integer +by @code{numeric}'s copy constructor but in an intermediate step it +holds a rational number 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 @acronym{CLN} is responsible for this +behaviour and we refer the reader to @acronym{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. @cartouche -@multitable @columnfractions .33 .66 +@multitable @columnfractions .33 .67 @item Method @tab Returns true if@dots{} @item @code{.is_zero()} @tab object is equal to zero @@ -1011,9 +917,11 @@ table. @node Constants, Fundamental operations, Numbers, Basic Concepts @c node-name, next, previous, up @section Constants +@cindex constants (class @code{constant}) +@cindex @code{evalf()} -Constants behave pretty much like symbols except that they return -some specific number when the method @code{.evalf()} is called. +Constants behave pretty much like symbols except that they return some +specific number when the method @code{.evalf()} is called. The predefined known constants are: @@ -1036,16 +944,20 @@ The predefined known constants are: @node Fundamental operations, Built-in functions, Constants, Basic Concepts @c node-name, next, previous, up @section Fundamental operations: the @code{power}, @code{add} and @code{mul} classes +@cindex polynomials +@cindex @code{add} +@cindex @code{mul} +@cindex @code{power} + +Simple polynomial expressions are written down in GiNaC pretty much like +in other CAS or like expressions involving numerical variables in C. +The necessary operators @code{+}, @code{-}, @code{*} and @code{/} have +been overloaded to achieve this goal. When you run the following +program, the constructor for an object of type @code{mul} is +automatically called to hold the product of @code{a} and @code{b} and +then the constructor for an object of type @code{add} is called to hold +the sum of that @code{mul} object and the number one: -Simple polynomial expressions are written down in GiNaC pretty -much like in other CAS. The necessary operators @code{+}, @code{-}, -@code{*} and @code{/} have been overloaded to achieve this goal. -When you run the following program, the constructor for an object of -type @code{mul} is automatically called to hold the product of @code{a} -and @code{b} and then the constructor for an object of type @code{add} -is called to hold the sum of that @code{mul} object and the number one: - -@subheading Construction of @code{add} and @code{mul} objects @example #include using namespace GiNaC; @@ -1079,50 +991,50 @@ for exclusive or. (It would be embarassing to return @code{1} where one has requested @code{2^3}.) @end itemize +@cindex @code{ginsh} All effects are contrary to mathematical notation and differ from the -way most other CAS handle exponentiation, therefore overloading -@code{^} is ruled out for GiNaC's C++ part. The situation -is different in @command{ginsh}, there the exponentiation-@code{^} -exists. (Also note, that the other frequently used exponentiation operator -@code{**} does not exist at all in C++). - -To be somewhat more precise, objects of the three classes -described here, are all containers for other expressions. An object -of class @code{power} is best viewed as a container with -two slots, one for the basis, one for the exponent. All valid GiNaC -expressions can be inserted. However, basic transformations like -simplifying @code{pow(pow(x,2),3)} to @code{x^6} automatically are only -performed when this is mathematically possible. If we replace the -outer exponent three in the example by some symbols @code{a}, the -simplification is not safe and will not be performed, since @code{a} -might be @code{1/2} and @code{x} negative. - -Objects of type @code{add} and @code{mul} are containers with an arbitrary -number of slots for expressions to be inserted. Again, simple and safe -simplifications are carried out like transforming @code{3*x+4-x} to -@code{2*x+4}. +way most other CAS handle exponentiation, therefore overloading @code{^} +is ruled out for GiNaC's C++ part. The situation is different in +@command{ginsh}, there the exponentiation-@code{^} exists. (Also note +that the other frequently used exponentiation operator @code{**} does +not exist at all in C++). + +To be somewhat more precise, objects of the three classes described +here, are all containers for other expressions. An object of class +@code{power} is best viewed as a container with two slots, one for the +basis, one for the exponent. All valid GiNaC expressions can be +inserted. However, basic transformations like simplifying +@code{pow(pow(x,2),3)} to @code{x^6} automatically are only performed +when this is mathematically possible. If we replace the outer exponent +three in the example by some symbols @code{a}, the simplification is not +safe and will not be performed, since @code{a} might be @code{1/2} and +@code{x} negative. + +Objects of type @code{add} and @code{mul} are containers with an +arbitrary number of slots for expressions to be inserted. Again, simple +and safe simplifications are carried out like transforming +@code{3*x+4-x} to @code{2*x+4}. The general rule is that when you construct such objects, GiNaC automatically creates them in canonical form, which might differ from -the form you typed in your program. This allows for rapid comparison -of expressions, since after all @code{a-a} is simply zero. -Note, that the canonical form is not necessarily lexicographical -ordering or in any way easily guessable. It is only guaranteed that -constructing the same expression twice, either implicitly or -explicitly, results in the same canonical form. +the form you typed in your program. This allows for rapid comparison of +expressions, since after all @code{a-a} is simply zero. Note, that the +canonical form is not necessarily lexicographical ordering or in any way +easily guessable. It is only guaranteed that constructing the same +expression twice, either implicitly or explicitly, results in the same +canonical form. @node Built-in functions, Important Algorithms, Fundamental operations, Basic Concepts @c node-name, next, previous, up @section Built-in functions -There are quite a number of useful functions built into GiNaC. -They are all objects of class @code{function}. They -accept one or more expressions as arguments and return one expression. -If the arguments are not numerical, the evaluation of the functions -may be halted, as it does in the next example: +There are quite a number of useful functions built into GiNaC. They are +all objects of class @code{function}. They accept one or more +expressions as arguments and return one expression. If the arguments +are not numerical, the evaluation of the function may be halted, as it +does in the next example: -@subheading Evaluation of built-in functions @example #include using namespace GiNaC; @@ -1141,7 +1053,7 @@ int main() @} @end example -This program will type out two times a function and then an +This program shows how the function returns itself twice and finally an expression that may be really useful: @example @@ -1151,21 +1063,21 @@ gamma(15/2) -> (135135/128)*Pi^(1/2) @end example Most of these functions can be differentiated, series expanded and so -on. Read the next chapter in order to learn more about this.. +on. Read the next chapter in order to learn more about this. @node Important Algorithms, Polynomial Expansion, Built-in functions, Top @c node-name, next, previous, up @chapter Important Algorithms +@cindex polynomials -In this chapter the most important algorithms provided by GiNaC -will be described. Some of them are implemented as functions on -expressions, others are implemented as methods provided by expression -objects. If they are methods, there exists a wrapper function around -it, so you can alternatively call it in a functional way as shown in -the simple example: +In this chapter the most important algorithms provided by GiNaC will be +described. Some of them are implemented as functions on expressions, +others are implemented as methods provided by expression objects. If +they are methods, there exists a wrapper function around it, so you can +alternatively call it in a functional way as shown in the simple +example: -@subheading Methods vs. wrapper functions @example #include using namespace GiNaC; @@ -1180,26 +1092,24 @@ int main() @} @end example -The general rule is that wherever methods accept one or more -parameters (@var{arg1}, @var{arg2}, @dots{}) the order of arguments -the function wrapper accepts is the same but preceded by the object -to act on (@var{object}, @var{arg1}, @var{arg2}, @dots{}). This -approach is the most natural one in an OO model but it may lead to -confusion for MapleV users because where they would type -@code{A:=x+1; subs(x=2,A);} GiNaC would require -@code{A=x+1; subs(A,x==2);} (after proper declaration of @code{A} -and @code{x}). On the other hand, since MapleV returns 3 on -@code{A:=x^2+3; coeff(A,x,0);} (GiNaC: -@code{A=pow(x,2)+3; coeff(A,x,0);}) it is clear that -MapleV is not trying to be consistent here. Also, users of MuPAD will -in most cases feel more comfortable with GiNaC's convention. All -function wrappers are always implemented as simple inline functions -which just call the corresponding method and are only provided for -users uncomfortable with OO who are dead set to avoid method -invocations. Generally, a chain of function wrappers is much harder -to read than a chain of methods and should therefore be avoided if -possible. On the other hand, not everything in GiNaC is a method on -class @code{ex} and sometimes calling a function cannot be +The general rule is that wherever methods accept one or more parameters +(@var{arg1}, @var{arg2}, @dots{}) the order of arguments the function +wrapper accepts is the same but preceded by the object to act on +(@var{object}, @var{arg1}, @var{arg2}, @dots{}). This approach is the +most natural one in an OO model but it may lead to confusion for MapleV +users because where they would type @code{A:=x+1; subs(x=2,A);} GiNaC +would require @code{A=x+1; subs(A,x==2);} (after proper declaration of +@code{A} and @code{x}). On the other hand, since MapleV returns 3 on +@code{A:=x^2+3; coeff(A,x,0);} (GiNaC: @code{A=pow(x,2)+3; +coeff(A,x,0);}) it is clear that MapleV is not trying to be consistent +here. Also, users of MuPAD will in most cases feel more comfortable +with GiNaC's convention. All function wrappers are always implemented +as simple inline functions which just call the corresponding method and +are only provided for users uncomfortable with OO who are dead set to +avoid method invocations. Generally, a chain of function wrappers is +much harder to read than a chain of methods and should therefore be +avoided if possible. On the other hand, not everything in GiNaC is a +method on class @code{ex} and sometimes calling a function cannot be avoided. @menu @@ -1214,55 +1124,56 @@ avoided. @node Polynomial Expansion, Collecting expressions, Important Algorithms, Important Algorithms @c node-name, next, previous, up @section Polynomial Expansion +@cindex @code{expand()} A polynomial in one or more variables has many equivalent representations. Some useful ones serve a specific purpose. Consider -for example the trivariate polynomial @math{4*x*y + x*z + 20*y^2 + 21*y*z + 4*z^2}. -It is equivalent to the factorized polynomial @math{(x + 5*y + 4*z)*(4*y + z)}. -Other representations are the recursive ones where one collects for -exponents in one of the three variable. Since the factors are -themselves polynomials in the remaining two variables the procedure -can be repeated. In our expample, two possibilies would be -@math{(4*y + z)*x + 20*y^2 + 21*y*z + 4*z^2} and -@math{20*y^2 + (21*z + 4*x)*y + 4*z^2 + x*z}. - -To bring an expression into expanded form, its method -@code{.expand()} may be called. In our example above, -this corresponds to @math{4*x*y + x*z + 20*y^2 + 21*y*z + 4*z^2}. -Again, since the canonical form in GiNaC is not easily guessable you -should be prepared to see different orderings of terms in such sums! +for example the trivariate polynomial @math{4*x*y + x*z + 20*y^2 + +21*y*z + 4*z^2} (written down here in output-style). It is equivalent +to the factorized polynomial @math{(x + 5*y + 4*z)*(4*y + z)}. Other +representations are the recursive ones where one collects for exponents +in one of the three variable. Since the factors are themselves +polynomials in the remaining two variables the procedure can be +repeated. In our expample, two possibilities would be @math{(4*y + z)*x ++ 20*y^2 + 21*y*z + 4*z^2} and @math{20*y^2 + (21*z + 4*x)*y + 4*z^2 + +x*z}. + +To bring an expression into expanded form, its method @code{.expand()} +may be called. In our example above, this corresponds to @math{4*x*y + +x*z + 20*y^2 + 21*y*z + 4*z^2}. Again, since the canonical form in +GiNaC is not easily guessable you should be prepared to see different +orderings of terms in such sums! @node Collecting expressions, Polynomial Arithmetic, Polynomial Expansion, Important Algorithms @c node-name, next, previous, up @section Collecting expressions +@cindex @code{collect()} +@cindex @code{coeff()} -Another useful representation of multivariate polynomials is as -a univariate polynomial in one of the variables with the coefficients +Another useful representation of multivariate polynomials is as a +univariate polynomial in one of the variables with the coefficients being polynomials in the remaining variables. The method -@code{collect()} accomplishes this task: +@code{collect()} accomplishes this task. Here is its declaration: @example -#include ex ex::collect(symbol const & s); @end example -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 +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 @example -#include int ex::degree(symbol const & s); int ex::ldegree(symbol const & s); @end example where @code{degree()} returns the highest coefficient and -@code{ldegree()} the lowest one. These two methods work -also reliably on non-expanded input polynomials. This is illustrated -in the following example: +@code{ldegree()} the lowest one. (These two methods work also reliably +on non-expanded input polynomials). An application is illustrated in +the next example, where a multivariate polynomial is analysed: -@subheading Collecting expressions in multivariate polynomials @example #include using namespace GiNaC; @@ -1294,9 +1205,9 @@ The x^3-coefficient is 4*y As polynomial in y: -x^2+(5*x+1)*y^2+(-2*x+4*x^3+11)*y @end example -As always, the exact output may vary between different versions of -GiNaC or even from run to run since the internal canonical ordering is -not within the user's sphere of influence. +As always, the exact output may vary between different versions of GiNaC +or even from run to run since the internal canonical ordering is not +within the user's sphere of influence. @node Polynomial Arithmetic, Symbolic Differentiation, Collecting expressions, Important Algorithms @@ -1304,24 +1215,23 @@ not within the user's sphere of influence. @section Polynomial Arithmetic @subsection GCD and LCM +@cindex GCD +@cindex LCM The functions for polynomial greatest common divisor and least common multiple have the synopsis: @example -#include ex gcd(const ex & a, const ex & b); ex lcm(const ex & a, const ex & b); @end example The functions @code{gcd()} and @code{lcm()} accept two expressions -@code{a} and @code{b} as arguments and return -a new expression, their greatest common divisor or least common -multiple, respectively. If the polynomials @code{a} and -@code{b} are coprime @code{gcd(a,b)} returns 1 and @code{lcm(a,b)} -returns the product of @code{a} and @code{b}. +@code{a} and @code{b} as arguments and return a new expression, their +greatest common divisor or least common multiple, respectively. If the +polynomials @code{a} and @code{b} are coprime @code{gcd(a,b)} returns 1 +and @code{lcm(a,b)} returns the product of @code{a} and @code{b}. -@subheading Polynomal GCD/LCM @example #include using namespace GiNaC; @@ -1341,6 +1251,8 @@ int main() @end example @subsection The @code{normal} method +@cindex @code{normal()} +@cindex temporary replacement While in common symbolic code @code{gcd()} and @code{lcm()} are not too heavily used, simplification is called for frequently. Therefore @@ -1354,7 +1266,6 @@ instance), that object is replaced by a temporary symbol. This means that both expressions @code{t1} and @code{t2} are indeed simplified in this little program: -@subheading Cancellation of polynomial GCD (with obstacles) @example #include using namespace GiNaC; @@ -1371,19 +1282,21 @@ int main() @end 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 @code{P_a/P_b} = @code{(4*y+z)/(y+3*z)}. +the sample-polynomials from the section about GCD and LCM above would be +normalized to @code{P_a/P_b} = @code{(4*y+z)/(y+3*z)}. @node Symbolic Differentiation, Series Expansion, Polynomial Arithmetic, Important Algorithms @c node-name, next, previous, up @section Symbolic Differentiation +@cindex differentiation +@cindex chain rule +@cindex product rule GiNaC's objects know how to differentiate themselves. Thus, a -polynomial (class @code{add}) knows that its derivative is -the sum of the derivatives of all the monomials: +polynomial (class @code{add}) knows that its derivative is the sum of +the derivatives of all the monomials: -@subheading Simple polynomial differentiation @example #include using namespace GiNaC; @@ -1403,20 +1316,19 @@ int main() If a second integer parameter @var{n} is given, the @code{diff} method returns the @var{n}th derivative. -If @emph{every} 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 @code{1/cosh(x)}. Since the -derivative of @code{cosh(x)} is @code{sinh(x)} -and the derivative of @code{pow(x,-1)} is -@code{-pow(x,-2)}, GiNaC can readily compute the -composition. It turns out that the composition is the generating -function for Euler Numbers, i.e. the so called -@var{n}th Euler number is the coefficient of @code{x^n/n!} in -the expansion of @code{1/cosh(x)}. We may use this identity to code a -function that generates Euler numbers in just three lines: - -@subheading Differentiation with nontrivial functions: Euler numbers +If @emph{every} 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 +@code{1/cosh(x)}. Since the derivative of @code{cosh(x)} is +@code{sinh(x)} and the derivative of @code{pow(x,-1)} is +@code{-pow(x,-2)}, GiNaC can readily compute the composition. It turns +out that the composition is the generating function for Euler Numbers, +i.e. the so called @var{n}th Euler number is the coefficient of +@code{x^n/n!} in the expansion of @code{1/cosh(x)}. We may use this +identity to code a function that generates Euler numbers in just three +lines: + +@cindex Euler numbers @example #include using namespace GiNaC; @@ -1444,6 +1356,9 @@ When you run it, it produces the sequence @code{1}, @code{-1}, @code{5}, @node Series Expansion, Extending GiNaC, Symbolic Differentiation, Important Algorithms @c node-name, next, previous, up @section Series Expansion +@cindex series expansion +@cindex Taylor expansion +@cindex Laurent expansion Expressions know how to expand themselves as a Taylor series or (more generally) a Laurent series. Similar to most conventional Computer @@ -1451,7 +1366,6 @@ Algebra Systems, no distinction is made between those two. There is a 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: -@subheading Series expansion @example #include using namespace GiNaC; @@ -1474,17 +1388,27 @@ int main() @} @end example -As an instructive application, let us calculate the numerical -value of Archimedes' constant (for which there already exists the -exbuilt-in constant @code{Pi}) using M@'echain's -mysterious formula @code{Pi==16*atan(1/5)-4*atan(1/239)}. -We may expand the arcus tangent around @code{0} and insert -the fractions @code{1/5} and @code{1/239}. -But, as we have seen, a series in GiNaC carries an order term with it. -The function @code{series_to_poly()} may be used to strip -this off: - -@subheading Series expansion using M@'echain's formula for @code{Pi} +@cindex M@'echain's formula +As an instructive application, let us calculate the numerical value of +Archimedes' constant +@tex +$\pi$ +@end tex +(for which there already exists the built-in constant @code{Pi}) +using M@'echain's amazing formula +@tex +$\pi=16$~atan~$\!\left(1 \over 5 \right)-4$~atan~$\!\left(1 \over 239 \right)$. +@end tex +@ifnottex +@math{Pi==16*atan(1/5)-4*atan(1/239)}. +@end ifnottex +We may expand the arcus tangent around @code{0} and insert the fractions +@code{1/5} and @code{1/239}. But, as we have seen, a series in GiNaC +carries an order term with it and the question arises what the system is +supposed to do when the fractions are plugged into that order term. The +solution is to use the function @code{series_to_poly()} to simply strip +the order term off: + @example #include using namespace GiNaC; @@ -1530,11 +1454,12 @@ When you run this program, it will type out: @c node-name, next, previous, up @chapter Extending GiNaC -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 GiNaC's many loose ends in order to -fulfill everybody's dreams. +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 +GiNaC's many loose ends in order to fulfill everybody's dreams. If you +develop some useful extension please don't hesitate to contact the GiNaC +authors---they will happily incorporate them into future versions. @menu * What does not belong into GiNaC:: What to avoid. @@ -1546,22 +1471,23 @@ fulfill everybody's dreams. @c node-name, next, previous, up @section 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 -@command{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 @command{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 built-in functions in GiNaC that do not know how -to evaluate themselves numerically to a precision declared at runtime -(using @code{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 bignum-package +@cindex @code{ginsh} +First of all, GiNaC's name must be read literally. It is designed to be +a library for use within C++. The tiny @command{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 +@command{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 built-in functions in GiNaC that do not know how to +evaluate themselves numerically to a precision declared at runtime +(using @code{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 bignum-package @acronym{CLN} is much better suited. @@ -1569,18 +1495,17 @@ to be inefficient. For this purpose, the underlying bignum-package @c node-name, next, previous, up @section Symbolic functions -The easiest and most instructive way to start with is probably -to implement your own function. Objects of class -@code{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 -@code{ex} as arguments and returning one -@code{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 -@code{eval} it. It could look something like this: +The easiest and most instructive way to start with is probably to +implement your own function. Objects of class @code{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 @code{ex} as arguments and returning +one @code{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 @code{eval} it. It could +look something like this: @example static ex cos_eval_method(ex const & x) @@ -1593,12 +1518,11 @@ static ex cos_eval_method(ex const & x) @} @end example -The last line returns @code{cos(x)} if we don't know what -else to do and stops a potential recursive evaluation by saying -@code{.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 @code{numeric}: +The last line returns @code{cos(x)} if we don't know what else to do and +stops a potential recursive evaluation by saying @code{.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 @code{numeric}: @example static ex cos_evalf_method(ex const & x) @@ -1617,27 +1541,28 @@ static ex cos_diff_method(ex const & x, unsigned diff_param) @} @end example -The second parameter is obligatory but uninteresting at this point. -It is used for correct handling of the product rule only. For Taylor +@cindex product rule +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. +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 @code{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: +Now that all the ingrediences for @code{cos} have been set up, 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: @example REGISTER_FUNCTION(cos, cos_eval_method, cos_evalf_method, cos_diff, NULL); @end example -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: +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: @example DECLARE_FUNCTION_1P(cos) @@ -1646,21 +1571,22 @@ DECLARE_FUNCTION_1P(cos) The suffix @code{_1P} stands for @emph{one parameter}. Of course, this implementation of @code{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 macro-intense classes. -We have done our best to avoid them where we can.) +(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.) That's it. May the source be with you! -@node A Comparison With Other CAS, Bibliography, Symbolic functions, Top +@node A Comparison With Other CAS, Internal Structures, Symbolic functions, Top @c node-name, next, previous, up @chapter A Comparison With Other CAS +@cindex advocacy -This chapter will give you some information on how GiNaC -compares to other, traditional Computer Algebra Systems, like -@emph{Maple}, @emph{Mathematica} or @emph{Reduce}, where it has -advantages and disadvantages over these systems. +This chapter will give you some information on how GiNaC compares to +other, traditional Computer Algebra Systems, like @emph{Maple}, +@emph{Mathematica} or @emph{Reduce}, where it has advantages and +disadvantages over these systems. @heading Advantages @@ -1671,62 +1597,58 @@ Algebra Systems, like @itemize @bullet @item -familiar language: all common CAS implement their own -proprietary grammar which you have to learn first (and maybe learn -again when your vendor chooses to "enhance" it). With GiNaC you -can write your program in common C++, which is standardized. +familiar language: all common CAS implement their own proprietary +grammar which you have to learn first (and maybe learn again when your +vendor chooses to "enhance" it). With GiNaC you can write your program +in common C++, which is standardized. @item -structured data types: you can build up structured data -types using @code{struct}s or @code{class}es -together with STL features instead of using unnamed lists of lists -of lists. +structured data types: you can build up structured data types using +@code{struct}s or @code{class}es together with STL features instead of +using unnamed lists of lists of lists. @item -strongly typed: in CAS, you usually have only one kind of -variables which can hold contents of an arbitrary type. This -4GL like feature is nice for novice programmers, but dangerous. +strongly typed: in CAS, you usually have only one kind of variables +which can hold contents of an arbitrary type. This 4GL like feature is +nice for novice programmers, but dangerous. @item -development tools: powerful development tools exist for -C++, like fancy editors (e.g. with automatic -indentation and syntax highlighting), debuggers, visualization -tools, documentation tools... +development tools: powerful development tools exist for C++, like fancy +editors (e.g. with automatic indentation and syntax highlighting), +debuggers, visualization tools, documentation tools... @item -modularization: C++ programs can -easily be split into modules by separating interface and -implementation. +modularization: C++ programs can easily be split into modules by +separating interface and implementation. @item -price: GiNaC is distributed under the GNU Public License -which means that it is free and available with source code. And -there are excellent C++-compilers for free, too. +price: GiNaC is distributed under the GNU Public License which means +that it is free and available with source code. And there are excellent +C++-compilers for free, too. @item -extendable: you can add your own classes to GiNaC, thus -extending it on a very low level. Compare this to a traditional -CAS that you can usually only extend on a high level by writing in -the language defined by the parser. In particular, it turns out -to be almost impossible to fix bugs in a traditional system. +extendable: you can add your own classes to GiNaC, thus extending it on +a very low level. Compare this to a traditional CAS that you can +usually only extend on a high level by writing in the language defined +by the parser. In particular, it turns out to be almost impossible to +fix bugs in a traditional system. @item -seemless integration: it is somewhere between difficult -and impossible to call CAS functions from within a program -written in C++ or any other programming -language and vice versa. With GiNaC, your symbolic routines -are part of your program. You can easily call third party -libraries, e.g. for numerical evaluation or graphical -interaction. All other approaches are much more cumbersome: they -range from simply ignoring the problem (i.e. @emph{Maple}) to providing a -method for "embedding" the system (i.e. @emph{Yacas}). +seemless integration: it is somewhere between difficult and impossible +to call CAS functions from within a program written in C++ or any other +programming language and vice versa. With GiNaC, your symbolic routines +are part of your program. You can easily call third party libraries, +e.g. for numerical evaluation or graphical interaction. All other +approaches are much more cumbersome: they range from simply ignoring the +problem (i.e. @emph{Maple}) to providing a method for "embedding" the +system (i.e. @emph{Yacas}). @item -efficiency: often large parts of a program do not need -symbolic calculations at all. Why use large integers for loop -variables or arbitrary precision arithmetics where double -accuracy is sufficient? For pure symbolic applications, -GiNaC is comparable in speed with other CAS. +efficiency: often large parts of a program do not need symbolic +calculations at all. Why use large integers for loop variables or +arbitrary precision arithmetics where double accuracy is sufficient? +For pure symbolic applications, GiNaC is comparable in speed with other +CAS. @end itemize @@ -1738,37 +1660,33 @@ Of course it also has some disadvantages: @itemize @bullet @item -not interactive: GiNaC programs have to be written in -an editor, compiled and executed. You cannot play with -expressions interactively. However, such an extension is not -inherently forbidden by design. In fact, two interactive -interfaces are possible: First, a simple shell that exposes GiNaC's -types to a command line can readily be written (and has been -written) and second, as a more consistent approach we plan -an integration with the @acronym{CINT} C++ interpreter. +not interactive: GiNaC programs have to be written in an editor, +compiled and executed. You cannot play with expressions interactively. +However, such an extension is not inherently forbidden by design. In +fact, two interactive interfaces are possible: First, a simple shell +that exposes GiNaC's types to a command line can readily be written (and +has been written) and second, as a more consistent approach we plan an +integration with the @acronym{CINT} C++ interpreter. @item -advanced features: GiNaC cannot compete with a program -like @emph{Reduce} which exists for more than -30 years now or @emph{Maple} which grows since -1981 by the work of dozens of programmers, with respect to -mathematical features. Integration, factorization, non-trivial -simplifications, limits etc. are missing in GiNaC (and are not -planned for the near future). +advanced features: GiNaC cannot compete with a program like +@emph{Reduce} which exists for more than 30 years now or @emph{Maple} +which grows since 1981 by the work of dozens of programmers, with +respect to mathematical features. Integration, factorization, +non-trivial simplifications, limits etc. are missing in GiNaC (and are +not planned for the near future). @item -portability: While the GiNaC library itself is designed -to avoid any platform dependent features (it should compile -on any ANSI compliant C++ compiler), the -currently used version of the CLN library (fast large integer and -arbitrary precision arithmetics) can be compiled only on systems -with a recently new C++ compiler from the -GNU Compiler Collection (@acronym{GCC}). GiNaC uses -recent language features like explicit constructors, mutable -members, RTTI, @code{dynamic_cast}s and STL, so ANSI compliance is meant -literally. Recent @acronym{GCC} versions starting at -2.95, although itself not yet ANSI compliant, support all needed -features. +portability: While the GiNaC library itself is designed to avoid any +platform dependent features (it should compile on any ANSI compliant C++ +compiler), the currently used version of the CLN library (fast large +integer and arbitrary precision arithmetics) can be compiled only on +systems with a recently new C++ compiler from the GNU Compiler +Collection (@acronym{GCC}). GiNaC uses recent language features like +explicit constructors, mutable members, RTTI, @code{dynamic_cast}s and +STL, so ANSI compliance is meant literally. Recent @acronym{GCC} +versions starting at 2.95, although itself not yet ANSI compliant, +support all needed features. @end itemize @@ -1776,21 +1694,185 @@ features. @heading Why C++? Why did we choose to implement GiNaC in C++ instead of Java or any other -language? C++ is not perfect: type checking is not strict -(casting is possible), separation between interface and implementation -is not complete, object oriented design is not enforced. The main -reason is the often scolded feature of operator overloading in -C++. While it may be true that operating on classes -with a @code{+} operator is rarely meaningful, it is -perfectly suited for algebraic expressions. Writing @math{3x+5y} as -@code{3*x+5*y} instead of @code{x.times(3).plus(y.times(5))} looks much more -natural. Furthermore, the main developers are more familiar with -C++ than with any other programming language. - - -@node Bibliography, Concept Index, A Comparison With Other CAS, Top +language? C++ is not perfect: type checking is not strict (casting is +possible), separation between interface and implementation is not +complete, object oriented design is not enforced. The main reason is +the often scolded feature of operator overloading in C++. While it may +be true that operating on classes with a @code{+} operator is rarely +meaningful, it is perfectly suited for algebraic expressions. Writing +@math{3x+5y} as @code{3*x+5*y} instead of +@code{x.times(3).plus(y.times(5))} looks much more natural. Furthermore, +the main developers are more familiar with C++ than with any other +programming language. + + +@node Internal Structures, Expressions are reference counted, A Comparison With Other CAS, Top +@c node-name, next, previous, up +@appendix Internal Structures + +@menu +* Expressions are reference counted:: +* Internal representation of products and sums:: +@end menu + +@node Expressions are reference counted, Internal representation of products and sums, Internal Structures, Internal Structures +@c node-name, next, previous, up +@appendixsection Expressions are reference counted + +@cindex reference counting +@cindex copy-on-write +@cindex garbage collection +An expression is extremely light-weight since internally it works like a +handle to the actual representation and really holds nothing more than a +pointer to some other object. What this means in practice is that +whenever you create two @code{ex} and set the second equal to the first +no copying process is involved. Instead, the copying takes place as soon +as you try to change the second. Consider the simple sequence of code: + +@example +#include +using namespace GiNaC; + +int main() +@{ + symbol x("x"), y("y"), z("z"); + ex e1, e2; + + e1 = sin(x + 2*y) + 3*z + 41; + e2 = e1; // e2 points to same object as e1 + cout << e2 << endl; // prints sin(x+2*y)+3*z+41 + e2 += 1; // e2 is copied into a new object + cout << e2 << endl; // prints sin(x+2*y)+3*z+42 + // ... +@} +@end example + +The line @code{e2 = e1;} creates a second expression pointing to the +object held already by @code{e1}. The time involved for this operation +is therefore constant, no matter how large @code{e1} was. Actual +copying, however, must take place in the line @code{e2 += 1;} because +@code{e1} and @code{e2} are not handles for the same object any more. +This concept is called @dfn{copy-on-write semantics}. It increases +performance considerably whenever one object occurs multiple times and +represents a simple garbage collection scheme because when an @code{ex} +runs out of scope its destructor checks whether other expressions handle +the object it points to too and deletes the object from memory if that +turns out not to be the case. A slightly less trivial example of +differentiation using the chain-rule should make clear how powerful this +can be: + +@example +#include +using namespace GiNaC; + +int main() +@{ + symbol x("x"), y("y"); + + ex e1 = x + 3*y; + ex e2 = pow(e1, 3); + ex e3 = diff(sin(e2), x); // first derivative of sin(e2) by x + cout << e1 << endl // prints x+3*y + << e2 << endl // prints (x+3*y)^3 + << e3 << endl; // prints 3*(x+3*y)^2*cos((x+3*y)^3) + // ... +@} +@end example + +Here, @code{e1} will actually be referenced three times while @code{e2} +will be referenced two times. When the power of an expression is built, +that expression needs not be copied. Likewise, since the derivative of +a power of an expression can be easily expressed in terms of that +expression, no copying of @code{e1} is involved when @code{e3} is +constructed. So, when @code{e3} is constructed it will print as +@code{3*(x+3*y)^2*cos((x+3*y)^3)} but the argument of @code{cos()} only +holds a reference to @code{e2} and the factor in front is just +@code{3*e1^2}. + +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. If you still have an uncertain feeling with copy-on-write +semantics, we recommend you have a look at the +@uref{http://www.cerfnet.com/~mpcline/c++-faq-lite/, C++-FAQ lite} by +Marshall Cline. Chapter 16 covers this issue and presents an +implementation which is pretty close to the one in GiNaC. + + +@node Internal representation of products and sums, Bibliography, Expressions are reference counted, Internal Structures +@c node-name, next, previous, up +@appendixsection Internal representation of products and sums + +@cindex representation +@cindex @code{add} +@cindex @code{mul} +@cindex @code{power} +Although it should be completely transparent for the user of +GiNaC a short discussion of this topic helps to understand the sources +and also explain performance to a large degree. Consider the +unexpanded symbolic expression +@tex +$2d^3 \left( 4a + 5b - 3 \right)$ +@end tex +@ifnottex +@math{2*d^3*(4*a+5*b-3)} +@end ifnottex +which could naively be represented by a tree of linear containers for +addition and multiplication, one container for exponentiation with base +and exponent and some atomic leaves of symbols and numbers in this +fashion: + +@image{repnaive} + +@cindex pair-wise representation +However, doing so results in a rather deeply nested tree which will +quickly become inefficient to manipulate. We can improve on this by +representing the sum instead as a sequence of terms, each one being a +pair of a purely numeric multiplicative coefficient and its rest. In +the same spirit we can store the multiplication as a sequence of terms, +each having a numeric exponent and a possibly complicated base, the tree +becomes much more flat: + +@image{reppair} + +The number @code{3} above the symbol @code{d} shows that @code{mul} +objects are treated similarly where the coefficients are interpreted as +@emph{exponents} now. Addition of sums of terms or multiplication of +products with numerical exponents can be coded to be very efficient with +such a pair-wise representation. Internally, this handling is performed +by most CAS in this way. It typically speeds up manipulations by an +order of magnitude. The overall multiplicative factor @code{2} and the +additive term @code{-3} look somewhat out of place in this +representation, however, since they are still carrying a trivial +exponent and multiplicative factor @code{1} respectively. Within GiNaC, +this is avoided by adding a field that carries an overall numeric +coefficient. This results in the realistic picture of internal +representation for +@tex +$2d^3 \left( 4a + 5b - 3 \right)$ +@end tex +@ifnottex +@math{2*d^3*(4*a+5*b-3)} +@end ifnottex +: + +@image{repreal} + +This also allows for a better handling of numeric radicals, since +@code{sqrt(2)} can now be carried along calculations. Now it should be +clear, why both classes @code{add} and @code{mul} are derived from the +same abstract class: the data representation is the same, only the +semantics differs. In the class hierarchy, methods for polynomial +expansion and the like are reimplemented for @code{add} and @code{mul}, +but the data structure is inherited from @code{expairseq}. + + + +@node Bibliography, Concept Index, Internal representation of products and sums, Top @c node-name, next, previous, up -@chapter Bibliography +@appendix Bibliography @itemize @minus{} -- 2.44.0 From cf7ab73a8d4bda4516f28e24d53d9fabc4b95d09 Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Mon, 29 Nov 1999 22:23:36 +0000 Subject: [PATCH 06/16] - corrected an error due to my ignorance WRT diff_param --- doc/tutorial/ginac.texi | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi index 2e307ba0..e6d2d1a1 100644 --- a/doc/tutorial/ginac.texi +++ b/doc/tutorial/ginac.texi @@ -1543,11 +1543,12 @@ static ex cos_diff_method(ex const & x, unsigned diff_param) @cindex product rule 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. +specifies which parameter to differentiate in a partial derivative in +case the function has more than one parameter and its main application +is for correct handling of the chain rule. 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 all the ingrediences for @code{cos} have been set up, we need to tell the system about it. This is done by a macro and we are not -- 2.44.0 From 9ccb50b7b120f7f8de0c6a8e383d65dab0743b79 Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Mon, 29 Nov 1999 22:46:04 +0000 Subject: [PATCH 07/16] - alignment fix. :-) --- AUTHORS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index aa9e3e70..40ee11ee 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,7 +1,7 @@ The GiNaC Group --------------- -Christian Bauer -Alexander Frink -Richard B. Kreckel +Christian Bauer +Alexander Frink +Richard Kreckel And others... -- 2.44.0 From a87e6ee6d794b99dcf3946e7dde969edafeb3295 Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Mon, 29 Nov 1999 22:46:23 +0000 Subject: [PATCH 08/16] - clarified timings --- INSTALL | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/INSTALL b/INSTALL index 05275655..9dba753c 100644 --- a/INSTALL +++ b/INSTALL @@ -44,11 +44,11 @@ also depending on optimization. To give you a rough idea of what you have to expect the following table may be helpful. It was measured on a P-III/500MHz with "enough" memory: -step: | value of $CXXFLAGS: | comment: - | -O0 | -O1 | -O2 | ---------------+-------+-------+-------+------------------------------- -make | ~4m | ~6m | ~10m | building shared and static lib -make check | ~2m | ~2m | ~7m | mostly due to compilation +step: | GCC optimization level: | comment: + | -O0 | -O1 | -O2 | +--------------+--------+--------+--------+------------------------------- +make | ~4m | ~6m | ~10m | building shared and static lib +make check | ~2m | ~2m | ~7m | mostly due to compilation Problems with CLN -- 2.44.0 From be0485a03e9886496eeb7e8cdc2cc5c95b848632 Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Mon, 29 Nov 1999 22:50:42 +0000 Subject: [PATCH 09/16] - changed function::diff() to be more tolerant by checking first if the nth argument when differentiated is non-zero and *then* building the sum. - added support for overloaded polygamma functions psi(x) and psi(n,x). - changed return code of atan2_diff to be somewhat simpler and adjusted check/differentiation.cpp to account for this. --- check/differentiation.cpp | 6 ++++ ginac/diff.cpp | 17 +++++---- ginac/inifcns.h | 10 +++++- ginac/inifcns_gamma.cpp | 73 +++++++++++++++++++++++++++++++-------- ginac/inifcns_trans.cpp | 4 +-- ginac/numeric.cpp | 8 +++++ ginac/numeric.h | 1 + 7 files changed, 96 insertions(+), 23 deletions(-) diff --git a/check/differentiation.cpp b/check/differentiation.cpp index 611342d0..0d963fed 100644 --- a/check/differentiation.cpp +++ b/check/differentiation.cpp @@ -234,10 +234,16 @@ static unsigned differentiation5(void) pow(y*b+pow(y,2)*x+a,-2)*pow(y,2))* pow(1+pow(a*x+b+y*pow(x,2),2)*pow(y*b+pow(y,2)*x+a,-2),-1); */ + /* d = pow(1+pow(a*x+b+y*pow(x,2),2)*pow(y*b+pow(y,2)*x+a,-2),-1) *pow(y*b+pow(y,2)*x+a,-1)*(a+2*y*x) +pow(y,2)*(-a*x-b-y*pow(x,2))* pow(pow(y*b+pow(y,2)*x+a,2)+pow(a*x+b+y*pow(x,2),2),-1); + */ + d = pow(y,2)*pow(pow(b+y*pow(x,2)+x*a,2)+pow(y*b+pow(y,2)*x+a,2),-1)* + (-b-y*pow(x,2)-x*a)+ + pow(pow(b+y*pow(x,2)+x*a,2)+pow(y*b+pow(y,2)*x+a,2),-1)* + (y*b+pow(y,2)*x+a)*(2*y*x+a); result += check_diff(e, x, d); return result; diff --git a/ginac/diff.cpp b/ginac/diff.cpp index 7b4d489b..2661fddb 100644 --- a/ginac/diff.cpp +++ b/ginac/diff.cpp @@ -175,17 +175,22 @@ ex power::diff(symbol const & s) const ex function::diff(symbol const & s) const { exvector new_seq; - - if (serial == function_index_Order) { - + + if (serial==function_index_Order) { // Order Term function only differentiates the argument return Order(seq[0].diff(s)); - } else { - // Chain rule + ex arg_diff; for (unsigned i=0; i!=seq.size(); i++) { - new_seq.push_back(mul(pdiff(i), seq[i].diff(s))); + arg_diff = seq[i].diff(s); + // We apply the chain rule only when it makes sense. This is not + // just for performance reasons but also to allow functions to + // throw when differentiated with respect to one of its arguments + // without running into trouble with our automatic full + // differentiation: + if (!arg_diff.is_zero()) + new_seq.push_back(mul(pdiff(i), arg_diff)); } } return add(new_seq); diff --git a/ginac/inifcns.h b/ginac/inifcns.h index ee737818..725c1ee7 100644 --- a/ginac/inifcns.h +++ b/ginac/inifcns.h @@ -87,8 +87,16 @@ DECLARE_FUNCTION_1P(zeta) DECLARE_FUNCTION_1P(gamma) /** Psi-function (aka polygamma-function). */ +extern unsigned function_index_psi1; +inline function psi(ex const & p1) { + return function(function_index_psi1, p1); +} +extern unsigned function_index_psi2; +inline function psi(ex const & p1, ex const & p2) { + return function(function_index_psi2, p1, p2); +} //DECLARE_FUNCTION_1P(psi) -DECLARE_FUNCTION_2P(psi) +//DECLARE_FUNCTION_2P(psi) /** Factorial function. */ DECLARE_FUNCTION_1P(factorial) diff --git a/ginac/inifcns_gamma.cpp b/ginac/inifcns_gamma.cpp index bb3a74e0..a208592f 100644 --- a/ginac/inifcns_gamma.cpp +++ b/ginac/inifcns_gamma.cpp @@ -46,19 +46,19 @@ static ex gamma_eval(ex const & x) { if (x.info(info_flags::numeric)) { // trap integer arguments: - if ( x.info(info_flags::integer) ) { + if (x.info(info_flags::integer)) { // gamma(n+1) -> n! for postitive n - if ( x.info(info_flags::posint) ) { + if (x.info(info_flags::posint)) { return factorial(ex_to_numeric(x).sub(numONE())); } else { return numZERO(); // Infinity. Throw? What? } } // trap half integer arguments: - if ( (x*2).info(info_flags::integer) ) { + if ((x*2).info(info_flags::integer)) { // trap positive x=(n+1/2) // gamma(n+1/2) -> Pi^(1/2)*(1*3*..*(2*n-1))/(2^n) - if ( (x*2).info(info_flags::posint) ) { + if ((x*2).info(info_flags::posint)) { numeric n = ex_to_numeric(x).sub(numHALF()); numeric coefficient = doublefactorial(n.mul(numTWO()).sub(numONE())); coefficient = coefficient.div(numTWO().power(n)); @@ -75,7 +75,7 @@ static ex gamma_eval(ex const & x) } return gamma(x).hold(); } - + static ex gamma_evalf(ex const & x) { BEGIN_TYPECHECK @@ -89,7 +89,7 @@ static ex gamma_diff(ex const & x, unsigned diff_param) { GINAC_ASSERT(diff_param==0); - return psi(exZERO(),x)*gamma(x); // diff(log(gamma(x)),x)==psi(0,x) + return psi(x)*gamma(x); // diff(log(gamma(x)),x)==psi(x) } static ex gamma_series(ex const & x, symbol const & s, ex const & point, int order) @@ -108,17 +108,57 @@ REGISTER_FUNCTION(gamma, gamma_eval, gamma_evalf, gamma_diff, gamma_series); // Psi-function (aka polygamma-function) ////////// +/** Evaluation of polygamma-function psi(x). + * Somebody ought to provide some good numerical evaluation some day... */ +static ex psi1_eval(ex const & x) +{ + if (x.info(info_flags::numeric)) { + // do some stuff... + } + return psi(x).hold(); +} + +static ex psi1_evalf(ex const & x) +{ + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + END_TYPECHECK(psi(x)) + + return psi(ex_to_numeric(x)); +} + +static ex psi1_diff(ex const & x, unsigned diff_param) +{ + GINAC_ASSERT(diff_param==0); + + return psi(exONE(), x); +} + +static ex psi1_series(ex const & x, symbol const & s, ex const & point, int order) +{ + throw(std::logic_error("Nobody told me how to series expand the psi function. :-(")); +} + +unsigned function_index_psi1 = function::register_new("psi", psi1_eval, psi1_evalf, psi1_diff, psi1_series); + +////////// +// Psi-functions (aka polygamma-functions) psi(0,x)==psi(x) +////////// + /** Evaluation of polygamma-function psi(n,x). * Somebody ought to provide some good numerical evaluation some day... */ -static ex psi_eval(ex const & n, ex const & x) +static ex psi2_eval(ex const & n, ex const & x) { + // psi(0,x) -> psi(x) + if (n.is_zero()) + return psi(x).hold(); if (n.info(info_flags::numeric) && x.info(info_flags::numeric)) { // do some stuff... } return psi(n, x).hold(); } - -static ex psi_evalf(ex const & n, ex const & x) + +static ex psi2_evalf(ex const & n, ex const & x) { BEGIN_TYPECHECK TYPECHECK(n,numeric) @@ -128,18 +168,23 @@ static ex psi_evalf(ex const & n, ex const & x) return psi(ex_to_numeric(n), ex_to_numeric(x)); } -static ex psi_diff(ex const & n, ex const & x, unsigned diff_param) +static ex psi2_diff(ex const & n, ex const & x, unsigned diff_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(diff_param<2); + if (diff_param==0) { + // d/dn psi(n,x) + throw(std::logic_error("cannot diff psi(n,x) with respect to n")); + } + // d/dx psi(n,x) return psi(n+1, x); } -static ex psi_series(ex const & n, ex const & x, symbol const & s, ex const & point, int order) +static ex psi2_series(ex const & n, ex const & x, symbol const & s, ex const & point, int order) { - throw(std::logic_error("Nobody told me how to series expand the psi function. :-(")); + throw(std::logic_error("Nobody told me how to series expand the psi functions. :-(")); } -REGISTER_FUNCTION(psi, psi_eval, psi_evalf, psi_diff, psi_series); +unsigned function_index_psi2 = function::register_new("psi", psi2_eval, psi2_evalf, psi2_diff, psi2_series); } // namespace GiNaC diff --git a/ginac/inifcns_trans.cpp b/ginac/inifcns_trans.cpp index 70eccdce..db502ca9 100644 --- a/ginac/inifcns_trans.cpp +++ b/ginac/inifcns_trans.cpp @@ -468,10 +468,10 @@ static ex atan2_diff(ex const & y, ex const & x, unsigned diff_param) if (diff_param==0) { // d/dy atan(y,x) - return pow(x*(1+y*y/(x*x)),-1); + return x*pow(pow(x,2)+pow(y,2),-1); } // d/dx atan(y,x) - return -y*pow(x*x+y*y,-1); + return -y*pow(pow(x,2)+pow(y,2),-1); } REGISTER_FUNCTION(atan2, atan2_eval, atan2_evalf, atan2_diff, NULL); diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp index bb2762a2..1cc1fa69 100644 --- a/ginac/numeric.cpp +++ b/ginac/numeric.cpp @@ -1084,6 +1084,14 @@ numeric gamma(numeric const & x) /** The psi function (aka polygamma function). * This is only a stub! */ +numeric psi(numeric const & x) +{ + clog << "psi(): Does anybody know good way to calculate this numerically?" << endl; + return numeric(0); +} + +/** The psi functions (aka polygamma functions). + * This is only a stub! */ numeric psi(numeric const & n, numeric const & x) { clog << "psi(): Does anybody know good way to calculate this numerically?" << endl; diff --git a/ginac/numeric.h b/ginac/numeric.h index 88b7d953..13c790fc 100644 --- a/ginac/numeric.h +++ b/ginac/numeric.h @@ -241,6 +241,7 @@ numeric acosh(numeric const & x); numeric atanh(numeric const & x); numeric zeta(numeric const & x); numeric gamma(numeric const & x); +numeric psi(numeric const & x); numeric psi(numeric const & n, numeric const & x); numeric factorial(numeric const & n); numeric doublefactorial(numeric const & n); -- 2.44.0 From c349526385abdaca21fabc53d23b603d4510abe0 Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Tue, 30 Nov 1999 22:06:14 +0000 Subject: [PATCH 10/16] - changed mul::print() to behave similar to add::print() --- ginac/print.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ginac/print.cpp b/ginac/print.cpp index 1df9cd2f..f90a40ce 100644 --- a/ginac/print.cpp +++ b/ginac/print.cpp @@ -146,7 +146,8 @@ void add::print(ostream & os, unsigned upper_precedence) const if (coeff.csgn()==-1) os << '-'; first=false; } - if (coeff.compare(numONE()) && coeff.compare(numMINUSONE())) { + if (!coeff.is_equal(numONE()) && + !coeff.is_equal(numMINUSONE())) { if (coeff.csgn()==-1) (numMINUSONE()*coeff).print(os, precedence); else @@ -168,10 +169,17 @@ void mul::print(ostream & os, unsigned upper_precedence) const debugmsg("mul print",LOGLEVEL_PRINT); if (precedence<=upper_precedence) os << "("; bool first=true; - if (!overall_coeff.is_equal(exONE())) { - overall_coeff.print(os,precedence); - first=false; + // first print the overall numeric coefficient: + if (ex_to_numeric(overall_coeff).csgn()==-1) os << '-'; + if (!overall_coeff.is_equal(exONE()) && + !overall_coeff.is_equal(exMINUSONE())) { + if (ex_to_numeric(overall_coeff).csgn()==-1) + (numMINUSONE()*overall_coeff).print(os, precedence); + else + overall_coeff.print(os, precedence); + os << '*'; } + // then proceed with the remaining factors: for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) { if (!first) { os << '*'; -- 2.44.0 From 0b1b69cae8f548d656e0955fc543dd14ab93a139 Mon Sep 17 00:00:00 2001 From: Christian Bauer Date: Wed, 1 Dec 1999 19:03:37 +0000 Subject: [PATCH 11/16] - added 'ginac-config' script and 'ginac.m4' macros to help making packages that use GiNaC - installation does no longer fail when HTML docs were disabled by configuration --- GiNaC.spec.in | 9 +- Makefile.am | 18 +++ Makefile.in | 88 ++++++++++-- autogen.sh | 6 + check/Makefile.in | 2 + configure | 21 ++- configure.in | 13 +- doc/Makefile.am | 4 + doc/Makefile.in | 66 +++++++-- doc/ginac-config.1 | 66 +++++++++ doc/reference/Makefile.am | 17 ++- doc/reference/Makefile.in | 19 ++- doc/tutorial/Makefile.am | 6 +- doc/tutorial/Makefile.in | 8 +- doc/tutorial/ginac.texi | 284 +++++++++++++++++++++++++++++++++++++- doc/tutorial/stamp-vti | 2 +- doc/tutorial/version.texi | 2 +- ginac-config.in | 57 ++++++++ ginac.m4 | 166 ++++++++++++++++++++++ ginac/Makefile.in | 2 + ginsh/Makefile.in | 2 + 21 files changed, 809 insertions(+), 49 deletions(-) create mode 100755 autogen.sh create mode 100644 doc/ginac-config.1 create mode 100644 ginac-config.in create mode 100644 ginac.m4 diff --git a/GiNaC.spec.in b/GiNaC.spec.in index 5d22b8cf..1b178a11 100644 --- a/GiNaC.spec.in +++ b/GiNaC.spec.in @@ -1,5 +1,4 @@ -# spec file for GiNaC (not relocatable) - +# Note that this is NOT a relocatable package %define ver @VERSION@ %define rel 1 %define prefix /usr @@ -63,4 +62,10 @@ rm -rf $RPM_BUILD_ROOT %{prefix}/info/* %{prefix}/man/man1/* %{prefix}/share/doc/GiNaC/* +%{prefix}/share/aclocal/* %{prefix}/bin/* + +%changelog +* Wed Dec 1 1999 Christian Bauer + +- aclocal macros get installed diff --git a/Makefile.am b/Makefile.am index 4262ecc4..32810046 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,3 +3,21 @@ SUBDIRS = ginac check ginsh doc # Requires automake 1.4 AUTOMAKE_OPTIONS = 1.4 + +# GiNaC runtime configuration script +bin_SCRIPTS = ginac-config + +# All the rest of the distributed files +EXTRA_DIST = autogen.sh ginac.m4 + +# M4 macro file for inclusion with autoconf +m4datadir = $(datadir)/aclocal +m4data_DATA = ginac.m4 + +# Rule to build tar-gzipped distribution package +$(PACKAGE)-$(VERSION).tar.gz: dist + +# Rule to build RPM distribution package +rpm: $(PACKAGE)-$(VERSION).tar.gz + cp $(PACKAGE)-$(VERSRION).tar.gz /usr/src/redhat/SOURCES + rpm -ba GiNaC.spec diff --git a/Makefile.in b/Makefile.in index 8f5c366e..a6e7630f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -68,7 +68,9 @@ DOXYGEN = @DOXYGEN@ DVIPS = @DVIPS@ FIG2DEV = @FIG2DEV@ GINACLIB_BINARY_AGE = @GINACLIB_BINARY_AGE@ +GINACLIB_CPPFLAGS = @GINACLIB_CPPFLAGS@ GINACLIB_INTERFACE_AGE = @GINACLIB_INTERFACE_AGE@ +GINACLIB_LIBS = @GINACLIB_LIBS@ GINACLIB_MAJOR_VERSION = @GINACLIB_MAJOR_VERSION@ GINACLIB_MICRO_VERSION = @GINACLIB_MICRO_VERSION@ GINACLIB_MINOR_VERSION = @GINACLIB_MINOR_VERSION@ @@ -99,14 +101,29 @@ SUBDIRS = ginac check ginsh doc # Requires automake 1.4 AUTOMAKE_OPTIONS = 1.4 + +# GiNaC runtime configuration script +bin_SCRIPTS = ginac-config + +# All the rest of the distributed files +EXTRA_DIST = autogen.sh ginac.m4 + +# M4 macro file for inclusion with autoconf +m4datadir = $(datadir)/aclocal +m4data_DATA = ginac.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = config.h -CONFIG_CLEAN_FILES = GiNaC.spec +CONFIG_CLEAN_FILES = GiNaC.spec ginac-config +SCRIPTS = $(bin_SCRIPTS) + +DATA = $(m4data_DATA) + DIST_COMMON = README ./stamp-h.in AUTHORS COPYING ChangeLog \ GiNaC.spec.in INSTALL Makefile.am Makefile.in NEWS acconfig.h \ acinclude.m4 aclocal.m4 config.guess config.h.in config.sub configure \ -configure.in install-sh ltconfig ltmain.sh missing mkinstalldirs +configure.in ginac-config.in install-sh ltconfig ltmain.sh missing \ +mkinstalldirs DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) @@ -159,6 +176,46 @@ distclean-hdr: maintainer-clean-hdr: GiNaC.spec: $(top_builddir)/config.status GiNaC.spec.in cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status +ginac-config: $(top_builddir)/config.status ginac-config.in + cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_SCRIPTS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \ + $(INSTALL_SCRIPT) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \ + else if test -f $(srcdir)/$$p; then \ + echo " $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \ + $(INSTALL_SCRIPT) $(srcdir)/$$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \ + else :; fi; fi; \ + done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + list='$(bin_SCRIPTS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \ + done + +install-m4dataDATA: $(m4data_DATA) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(m4datadir) + @list='$(m4data_DATA)'; for p in $$list; do \ + if test -f $(srcdir)/$$p; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(m4datadir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(m4datadir)/$$p; \ + else if test -f $$p; then \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(m4datadir)/$$p"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(m4datadir)/$$p; \ + fi; fi; \ + done + +uninstall-m4dataDATA: + @$(NORMAL_UNINSTALL) + list='$(m4data_DATA)'; for p in $$list; do \ + rm -f $(DESTDIR)$(m4datadir)/$$p; \ + done # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. @@ -323,23 +380,24 @@ installcheck: installcheck-recursive all-recursive-am: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive -install-exec-am: +install-exec-am: install-binSCRIPTS install-exec: install-exec-recursive -install-data-am: +install-data-am: install-m4dataDATA install-data: install-data-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install: install-recursive -uninstall-am: +uninstall-am: uninstall-binSCRIPTS uninstall-m4dataDATA uninstall: uninstall-recursive -all-am: Makefile config.h +all-am: Makefile $(SCRIPTS) $(DATA) config.h all-redirect: all-recursive-am install-strip: $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install installdirs: installdirs-recursive installdirs-am: + $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(m4datadir) mostlyclean-generic: @@ -374,10 +432,12 @@ maintainer-clean: maintainer-clean-recursive -rm -f config.status .PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ -install-data-recursive uninstall-data-recursive install-exec-recursive \ -uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ -all-recursive check-recursive installcheck-recursive info-recursive \ -dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ +uninstall-binSCRIPTS install-binSCRIPTS uninstall-m4dataDATA \ +install-m4dataDATA install-data-recursive uninstall-data-recursive \ +install-exec-recursive uninstall-exec-recursive installdirs-recursive \ +uninstalldirs-recursive all-recursive check-recursive \ +installcheck-recursive info-recursive dvi-recursive \ +mostlyclean-recursive distclean-recursive clean-recursive \ maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \ @@ -387,6 +447,14 @@ installdirs mostlyclean-generic distclean-generic clean-generic \ maintainer-clean-generic clean mostlyclean distclean maintainer-clean +# Rule to build tar-gzipped distribution package +$(PACKAGE)-$(VERSION).tar.gz: dist + +# Rule to build RPM distribution package +rpm: $(PACKAGE)-$(VERSION).tar.gz + cp $(PACKAGE)-$(VERSRION).tar.gz /usr/src/redhat/SOURCES + rpm -ba GiNaC.spec + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 00000000..0e0fc0f8 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,6 @@ +#! /bin/sh +aclocal +autoheader +autoconf +automake +./configure $* diff --git a/check/Makefile.in b/check/Makefile.in index 8a503c7f..9189758a 100644 --- a/check/Makefile.in +++ b/check/Makefile.in @@ -68,7 +68,9 @@ DOXYGEN = @DOXYGEN@ DVIPS = @DVIPS@ FIG2DEV = @FIG2DEV@ GINACLIB_BINARY_AGE = @GINACLIB_BINARY_AGE@ +GINACLIB_CPPFLAGS = @GINACLIB_CPPFLAGS@ GINACLIB_INTERFACE_AGE = @GINACLIB_INTERFACE_AGE@ +GINACLIB_LIBS = @GINACLIB_LIBS@ GINACLIB_MAJOR_VERSION = @GINACLIB_MAJOR_VERSION@ GINACLIB_MICRO_VERSION = @GINACLIB_MICRO_VERSION@ GINACLIB_MINOR_VERSION = @GINACLIB_MINOR_VERSION@ diff --git a/configure b/configure index f455579d..4a6e3d2c 100755 --- a/configure +++ b/configure @@ -2670,10 +2670,15 @@ fi esac +GINACLIB_CPPFLAGS=$CPPFLAGS +GINACLIB_LIBS=$LIBS + + + # Extract the first word of "doxygen", so it can be a program name with args. set dummy doxygen; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2677: checking for $ac_word" >&5 +echo "configure:2682: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_DOXYGEN'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2709,7 +2714,7 @@ fi # Extract the first word of "latex", so it can be a program name with args. set dummy latex; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2713: checking for $ac_word" >&5 +echo "configure:2718: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_LATEX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2745,7 +2750,7 @@ fi # Extract the first word of "makeindex", so it can be a program name with args. set dummy makeindex; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2749: checking for $ac_word" >&5 +echo "configure:2754: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_MAKEINDEX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2781,7 +2786,7 @@ fi # Extract the first word of "dvips", so it can be a program name with args. set dummy dvips; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2785: checking for $ac_word" >&5 +echo "configure:2790: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_DVIPS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2817,7 +2822,7 @@ fi # Extract the first word of "fig2dev", so it can be a program name with args. set dummy fig2dev; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2821: checking for $ac_word" >&5 +echo "configure:2826: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_FIG2DEV'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2972,6 +2977,7 @@ ac_given_INSTALL="$INSTALL" trap 'rm -fr `echo " Makefile GiNaC.spec +ginac-config ginac/Makefile check/Makefile ginsh/Makefile @@ -3058,6 +3064,8 @@ s%@CPP@%$CPP%g s%@LEX_OUTPUT_ROOT@%$LEX_OUTPUT_ROOT%g s%@YACC@%$YACC%g s%@GINSH_LIBS@%$GINSH_LIBS%g +s%@GINACLIB_CPPFLAGS@%$GINACLIB_CPPFLAGS%g +s%@GINACLIB_LIBS@%$GINACLIB_LIBS%g s%@DOXYGEN@%$DOXYGEN%g s%@LATEX@%$LATEX%g s%@MAKEINDEX@%$MAKEINDEX%g @@ -3108,6 +3116,7 @@ cat >> $CONFIG_STATUS <> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h - +chmod +x ginac-config exit 0 EOF chmod +x $CONFIG_STATUS diff --git a/configure.in b/configure.in index a1a3903d..96be9d36 100644 --- a/configure.in +++ b/configure.in @@ -93,6 +93,12 @@ dnl We need to have Bruno Haible's CLN installed (macros are in acinclude.m4): GINAC_CHECK_CLN_H GINAC_CHECK_LIBCLN +dnl Expand the cppflags and libraries needed by apps using GiNaC +GINACLIB_CPPFLAGS=$CPPFLAGS +GINACLIB_LIBS=$LIBS +AC_SUBST(GINACLIB_CPPFLAGS) +AC_SUBST(GINACLIB_LIBS) + dnl Check for utilities needed by the different kinds of documentation. dnl Documantation needs only be built when extending it, so never mind if it dnl cannot find those helpers: @@ -120,17 +126,16 @@ fi AC_SUBST(TUTORIAL_TARGETS) AC_SUBST(REFERENCE_TARGETS) -dnl =========================================================================== -dnl Produce a Makefile from Makefile.in: -dnl =========================================================================== +dnl Output makefiles etc. AC_OUTPUT([ Makefile GiNaC.spec +ginac-config ginac/Makefile check/Makefile ginsh/Makefile doc/Makefile doc/tutorial/Makefile doc/reference/Makefile -]) +], [chmod +x ginac-config]) echo "Configuration done. Now type \"make\"." diff --git a/doc/Makefile.am b/doc/Makefile.am index e5de20e3..51716948 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,2 +1,6 @@ ## Process this file with automake to produce Makefile.in SUBDIRS = tutorial reference + +# Manual pages +man_MANS = ginac-config.1 +EXTRA_DIST = $(man_MANS) diff --git a/doc/Makefile.in b/doc/Makefile.in index ce4f7fd6..2498724b 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -68,7 +68,9 @@ DOXYGEN = @DOXYGEN@ DVIPS = @DVIPS@ FIG2DEV = @FIG2DEV@ GINACLIB_BINARY_AGE = @GINACLIB_BINARY_AGE@ +GINACLIB_CPPFLAGS = @GINACLIB_CPPFLAGS@ GINACLIB_INTERFACE_AGE = @GINACLIB_INTERFACE_AGE@ +GINACLIB_LIBS = @GINACLIB_LIBS@ GINACLIB_MAJOR_VERSION = @GINACLIB_MAJOR_VERSION@ GINACLIB_MICRO_VERSION = @GINACLIB_MICRO_VERSION@ GINACLIB_MINOR_VERSION = @GINACLIB_MINOR_VERSION@ @@ -96,9 +98,17 @@ VERSION = @VERSION@ YACC = @YACC@ SUBDIRS = tutorial reference + +# Manual pages +man_MANS = ginac-config.1 +EXTRA_DIST = $(man_MANS) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../config.h CONFIG_CLEAN_FILES = +man1dir = $(mandir)/man1 +MANS = $(man_MANS) + +NROFF = nroff DIST_COMMON = Makefile.am Makefile.in @@ -116,6 +126,45 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status +install-man1: + $(mkinstalldirs) $(DESTDIR)$(man1dir) + @list='$(man1_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \ + done + +uninstall-man1: + @list='$(man1_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \ + rm -f $(DESTDIR)$(man1dir)/$$inst; \ + done +install-man: $(MANS) + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-man1 +uninstall-man: + @$(NORMAL_UNINSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-man1 + # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, @@ -246,20 +295,21 @@ installcheck: installcheck-recursive install-exec-am: install-exec: install-exec-recursive -install-data-am: +install-data-am: install-man install-data: install-data-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am install: install-recursive -uninstall-am: +uninstall-am: uninstall-man uninstall: uninstall-recursive -all-am: Makefile +all-am: Makefile $(MANS) all-redirect: all-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install installdirs: installdirs-recursive installdirs-am: + $(mkinstalldirs) $(DESTDIR)$(mandir)/man1 mostlyclean-generic: @@ -291,11 +341,11 @@ maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \ maintainer-clean: maintainer-clean-recursive -.PHONY: install-data-recursive uninstall-data-recursive \ -install-exec-recursive uninstall-exec-recursive installdirs-recursive \ -uninstalldirs-recursive all-recursive check-recursive \ -installcheck-recursive info-recursive dvi-recursive \ -mostlyclean-recursive distclean-recursive clean-recursive \ +.PHONY: install-man1 uninstall-man1 install-man uninstall-man \ +install-data-recursive uninstall-data-recursive install-exec-recursive \ +uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ +all-recursive check-recursive installcheck-recursive info-recursive \ +dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ diff --git a/doc/ginac-config.1 b/doc/ginac-config.1 new file mode 100644 index 00000000..109da7d4 --- /dev/null +++ b/doc/ginac-config.1 @@ -0,0 +1,66 @@ +.TH ginac-config 1 "December 1999" "GiNaC" +.SH NAME +ginac-config \- script to get information about the installed version of GiNaC +.SH SYNOPSIS +.B ginac-config +.RI [\-\-prefix [=DIR] ] +.RI [\-\-exec\-prefix [=DIR] ] +[\-\-version] [\-\-libs] [\-\-cflags] +.SH DESCRIPTION +.B ginac-config +is a tool that is used to configure to determine the compiler and linker +flags that should be used to compile and link programs that use \fIGiNaC\fP. +It is also used internally to the .m4 macros for GNU autoconf that are +included with \fIGiNaC\fP. +.SH OPTIONS +.TP +.B \-\-version +prints the currently installed version of \fIGiNaC\fP on the standard output. +.TP +.B \-\-libs +prints the linker flags that are necessary to link a \fIGiNaC\fP program. +.TP +.B \-\-cflags +prints the compiler flags that are necessary to compile a \fIGiNaC\fP program. +.TP +.BI "\-\-prefix=" PREFIX +If specified, use PREFIX instead of the installation prefix that \fIGiNaC\fP +was built with when computing the output for the \-\-cflags and +\-\-libs options. This option is also used for the exec prefix +if \-\-exec\-prefix was not specified. This option must be specified +before any \-\-libs or \-\-cflags options. +.TP +.BI "\-\-exec\-prefix=" PREFIX +If specified, use PREFIX instead of the installation exec prefix that +\fIGiNaC\fP was built with when computing the output for the \-\-cflags +and \-\-libs options. This option must be specified before any +\-\-libs or \-\-cflags options. +.SH AUTHOR +.TP +The GiNaC Group: +.br +Christian Bauer +.br +Alexander Frink +.br +Richard B. Kreckel +.SH SEE ALSO +GiNaC Tutorial \- An open framework for symbolic computation within the +C++ programming language +.SH COPYRIGHT +Copyright \(co 1999 Johannes Gutenberg Universit\(:at Mainz, Germany +Based on gtk-config Copyright \(co 1998 Owen Taylor + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. diff --git a/doc/reference/Makefile.am b/doc/reference/Makefile.am index 23389186..db541b8b 100644 --- a/doc/reference/Makefile.am +++ b/doc/reference/Makefile.am @@ -51,14 +51,21 @@ CLEANFILES = *.html *.gif doxygen.css *.ps latex/* EXTRA_DIST = DoxyfileHTML DoxyfileTEX Doxyfooter install-data-local: - $(INSTALL_DATA) $(srcdir)/doxygen.css $(DESTDIR)$(ginacreferencedir)/doxygen.css + @if [ -f $(srcdir)/doxygen.css ]; then \ + echo " $(INSTALL_DATA) $(srcdir)/doxygen.css $(DESTDIR)$(ginacreferencedir)/doxygen.css"; \ + $(INSTALL_DATA) $(srcdir)/doxygen.css $(DESTDIR)$(ginacreferencedir)/doxygen.css; \ + fi @for p in *.html; do \ - echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p"; \ - $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p; \ + if [ -f $(srcdir)/$$p ]; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p; \ + fi; \ done @for p in *.gif; do \ - echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p"; \ - $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p; \ + if [ -f $(srcdir)/$$p ]; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p; \ + fi; \ done uninstall-local: diff --git a/doc/reference/Makefile.in b/doc/reference/Makefile.in index 00fa110d..152e777b 100644 --- a/doc/reference/Makefile.in +++ b/doc/reference/Makefile.in @@ -71,7 +71,9 @@ DOXYGEN = @DOXYGEN@ DVIPS = @DVIPS@ FIG2DEV = @FIG2DEV@ GINACLIB_BINARY_AGE = @GINACLIB_BINARY_AGE@ +GINACLIB_CPPFLAGS = @GINACLIB_CPPFLAGS@ GINACLIB_INTERFACE_AGE = @GINACLIB_INTERFACE_AGE@ +GINACLIB_LIBS = @GINACLIB_LIBS@ GINACLIB_MAJOR_VERSION = @GINACLIB_MAJOR_VERSION@ GINACLIB_MICRO_VERSION = @GINACLIB_MICRO_VERSION@ GINACLIB_MINOR_VERSION = @GINACLIB_MINOR_VERSION@ @@ -275,14 +277,21 @@ reference.ps: latex latex/reference.ps cp ${srcdir}/latex/reference.ps reference.ps install-data-local: - $(INSTALL_DATA) $(srcdir)/doxygen.css $(DESTDIR)$(ginacreferencedir)/doxygen.css + @if [ -f $(srcdir)/doxygen.css ]; then \ + echo " $(INSTALL_DATA) $(srcdir)/doxygen.css $(DESTDIR)$(ginacreferencedir)/doxygen.css"; \ + $(INSTALL_DATA) $(srcdir)/doxygen.css $(DESTDIR)$(ginacreferencedir)/doxygen.css; \ + fi @for p in *.html; do \ - echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p"; \ - $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p; \ + if [ -f $(srcdir)/$$p ]; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p; \ + fi; \ done @for p in *.gif; do \ - echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p"; \ - $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p; \ + if [ -f $(srcdir)/$$p ]; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginacreferencedir)/$$p; \ + fi; \ done uninstall-local: diff --git a/doc/tutorial/Makefile.am b/doc/tutorial/Makefile.am index 5eb24799..a2763b1c 100644 --- a/doc/tutorial/Makefile.am +++ b/doc/tutorial/Makefile.am @@ -41,8 +41,10 @@ EXTRA_DIST = $(FIG) $(TXT) install-data-local: @for p in $(PNG); do \ - echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginactutorialdir)/$$p"; \ - $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginactutorialdir)/$$p; \ + if [ -f $(srcdir)/$$p ]; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginactutorialdir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginactutorialdir)/$$p; \ + fi; \ done uninstall-local: diff --git a/doc/tutorial/Makefile.in b/doc/tutorial/Makefile.in index 8c17b366..c1715667 100644 --- a/doc/tutorial/Makefile.in +++ b/doc/tutorial/Makefile.in @@ -70,7 +70,9 @@ DOXYGEN = @DOXYGEN@ DVIPS = @DVIPS@ FIG2DEV = @FIG2DEV@ GINACLIB_BINARY_AGE = @GINACLIB_BINARY_AGE@ +GINACLIB_CPPFLAGS = @GINACLIB_CPPFLAGS@ GINACLIB_INTERFACE_AGE = @GINACLIB_INTERFACE_AGE@ +GINACLIB_LIBS = @GINACLIB_LIBS@ GINACLIB_MAJOR_VERSION = @GINACLIB_MAJOR_VERSION@ GINACLIB_MICRO_VERSION = @GINACLIB_MICRO_VERSION@ GINACLIB_MINOR_VERSION = @GINACLIB_MINOR_VERSION@ @@ -414,8 +416,10 @@ ginac.html: ginac.texi version.texi $(PNG) install-data-local: @for p in $(PNG); do \ - echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginactutorialdir)/$$p"; \ - $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginactutorialdir)/$$p; \ + if [ -f $(srcdir)/$$p ]; then \ + echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginactutorialdir)/$$p"; \ + $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(ginactutorialdir)/$$p; \ + fi; \ done uninstall-local: diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi index e6d2d1a1..5e47963a 100644 --- a/doc/tutorial/ginac.texi +++ b/doc/tutorial/ginac.texi @@ -86,6 +86,7 @@ framework for symbolic computation within the C++ programming language. * Extending GiNaC:: How to extend the library. * A Comparison With Other CAS:: Compares GiNaC to traditional CAS. * Internal Structures:: Description of some internal structures. +* Package Tools:: Configuring packages to work with GiNaC. * Bibliography:: * Concept Index:: @end menu @@ -203,6 +204,9 @@ $ ./hello 355687428096000*x*y+20922789888000*y^2+6402373705728000*x^2 @end example +(@xref{Package Tools}, for tools that help you when creating a software +package that uses GiNaC.) + @cindex Hermite polynomial Next, there is a more meaningful C++ program that calls a function which generates Hermite polynomials in a specified free variable. @@ -600,6 +604,7 @@ configuration again with the same @var{PREFIX} thus creating a do it by hand since you now know where all the files went during installation.}. + @node Basic Concepts, Expressions, Installing GiNaC, Top @c node-name, next, previous, up @chapter Basic Concepts @@ -642,7 +647,7 @@ ex MyEx5 = MyEx4 + 1; // similar to above Expressions are handles to other more fundamental objects, that many times contain other expressions thus creating a tree of expressions -(@xref{Internal Structures} for particular examples). Most methods on +(@xref{Internal Structures}, for particular examples). Most methods on @code{ex} therefore run top-down through such an expression tree. For example, the method @code{has()} scans recursively for occurrences of something inside an expression. Thus, if you have declared @code{MyEx4} @@ -1802,7 +1807,7 @@ Marshall Cline. Chapter 16 covers this issue and presents an implementation which is pretty close to the one in GiNaC. -@node Internal representation of products and sums, Bibliography, Expressions are reference counted, Internal Structures +@node Internal representation of products and sums, Package Tools, Expressions are reference counted, Internal Structures @c node-name, next, previous, up @appendixsection Internal representation of products and sums @@ -1870,8 +1875,281 @@ expansion and the like are reimplemented for @code{add} and @code{mul}, but the data structure is inherited from @code{expairseq}. +@node Package Tools, ginac-config, Internal representation of products and sums, Top +@c node-name, next, previous, up +@appendix Package Tools + +If you are creating a software package that uses the GiNaC library, +setting the correct command line options for the compiler and linker +can be difficult. GiNaC includes two tools to make this process easier. + +@menu +* ginac-config:: A shell script to detect compiler and linker flags. +* AM_PATH_GINAC:: Macro for GNU automake. +@end menu + + +@node ginac-config, AM_PATH_GINAC, Package Tools, Package Tools +@c node-name, next, previous, up +@section @command{ginac-config} +@cindex ginac-config + +@command{ginac-config} is a shell script that you can use to determine +the compiler and linker command line options required to compile and +link a program with the GiNaC library. + +@command{ginac-config} takes the following flags: + +@table @samp +@item --version +Prints out the version of GiNaC installed. +@item --cppflags +Prints '-I' flags pointing to the installed header files. +@item --libs +Prints out the linker flags necessary to link a program against GiNaC. +@item --prefix[=@var{PREFIX}] +If @var{PREFIX} is specified, overrides the configured value of @env{$prefix}. +(And of exec-prefix, unless --exec-prefix is also specified) +Otherwise, prints out the configured value of @env{$prefix}. +@item --exec-prefix[=@var{PREFIX}] +If @var{PREFIX} is specified, overrides the configured value of @env{$exec_prefix}. +Otherwise, prints out the configured value of @env{$exec_prefix}. +@end table + +Typically, @command{ginac-config} will be used within a configure script, +as described below. It, however, can also be used directly +from the command line to compile a simple program. For example: + +@example +c++ -o simple `ginac-config --cppflags` simple.cpp `ginac-config --libs` +@end example + +This command line might expand to (for example): + +@example +cc -o simple -I/usr/local/include simple.cpp -L/usr/local/lib \ + -lginac -lcln -lstdc++ +@end example + +Not only is the form using @command{ginac-config} easier to type, it will +work on any system, no matter how GiNaC was configured. + + +@node AM_PATH_GINAC, Configure script options, ginac-config, Package Tools +@c node-name, next, previous, up +@section @samp{AM_PATH_GINAC} +@cindex AM_PATH_GINAC + +For packages configured using GNU automake, GiNaC also provides +a macro to automate the process of checking for GiNaC. + +@example +AM_PATH_GINAC([@var{MINIMUM-VERSION}, [@var{ACTION-IF-FOUND} [, @var{ACTION-IF-NOT-FOUND}]]]) +@end example + +This macro: + +@itemize @bullet + +@item +Determines the location of GiNaC using @command{ginac-config}, which is +either found in the user's path, or from the environment variable +@env{GINACLIB_CONFIG}. + +@item +Tests the installed libraries to make sure that there version +is later than @var{MINIMUM-VERSION}. (A default version will be used +if not specified) + +@item +If the required version was found, sets the @env{GINACLIB_CPPFLAGS} variable +to the output of @command{ginac-config --cppflags} and the @env{GINACLIB_LIBS} +variable to the output of @command{ginac-config --libs}, and calls +@samp{AC_SUBST()} for these variables so they can be used in generated +makefiles, and then executes @var{ACTION-IF-FOUND}. + +@item +If the required version was not found, sets @env{GINACLIB_CPPFLAGS} and +@env{GINACLIB_LIBS} to empty strings, and executes @var{ACTION-IF-NOT-FOUND}. + +@end itemize + +This macro is in file @file{ginac.m4} which is installed in +@file{$datadir/aclocal}. Note that if automake was installed with a +different @samp{--prefix} than GiNaC, you will either have to manually +move @file{ginac.m4} to automake's @file{$datadir/aclocal}, or give +aclocal the @samp{-I} option when running it. + +@menu +* Configure script options:: Configuring a package that uses AM_PATH_GINAC. +* Example package:: Example of a package using AM_PATH_GINAC. +@end menu + + +@node Configure script options, Example package, AM_PATH_GINAC, AM_PATH_GINAC +@c node-name, next, previous, up +@subsection Configuring a package that uses @samp{AM_PATH_GINAC} + +Simply make sure that @command{ginac-config} is in your path, and run +the configure script. + +Notes: + +@itemize @bullet + +@item +The directory where the GiNaC libraries are installed needs +to be found by your system's dynamic linker. + +This is generally done by + +@display +editing @file{/etc/ld.so.conf} and running @command{ldconfig} +@end display + +or by + +@display +setting the environment variable @env{LD_LIBRARY_PATH}, +@end display + +or, as a last resort, + +@display +giving a @samp{-R} or @samp{-rpath} flag (depending on your linker) when +running configure, for instance: + +@example +LDFLAGS=-R/home/cbauer/lib ./configure +@end example +@end display + +@item +You can also specify a @command{ginac-config} not in your path by +setting the @env{GINACLIB_CONFIG} environment variable to the +name of the executable + +@item +If you move the GiNaC package from its installed location, +you will need either need to modify @command{ginac-config} script +manually to point to the new location or rebuild GiNaC. + +@end itemize + +Advanced note: + +@itemize @bullet +@item +configure flags + +@example +--with-ginac-prefix=@var{PREFIX} +--with-ginac-exec-prefix=@var{PREFIX} +@end example + +are provided to override the prefix and exec-prefix that were stored +in the @command{ginac-config} shell script by GiNaC's configure. You are +generally better off configuring GiNaC with the right path to begin with. +@end itemize + + +@node Example package, Bibliography, Configure script options, AM_PATH_GINAC +@c node-name, next, previous, up +@subsection Example of a package using @samp{AM_PATH_GINAC} + +The following shows how to build a simple package using automake +and the @samp{AM_PATH_GINAC} macro. The program used here is @file{simple.cpp}: + +@example +#include +using namespace GiNaC; + +int main(void) +@{ + symbol x("x"); + ex a = sin(x); + cout << "Derivative of " << a << " is " << a.diff(x) << endl; + return 0; +@} +@end example + +You should first read the introductory portions of the automake +Manual, if you are not already familiar with it. + +Two files are needed, @file{configure.in}, which is used to build the +configure script: + +@example +dnl Process this file with autoconf to produce a configure script. +AC_INIT(simple.cpp) +AM_INIT_AUTOMAKE(simple.cpp, 1.0.0) + +AC_PROG_CXX +AC_PROG_INSTALL +AC_LANG_CPLUSPLUS + +AM_PATH_GINAC(0.4.0, [ + LIBS="$LIBS $GINACLIB_LIBS" + CPPFLAGS="$CFLAGS $GINACLIB_CPPFLAGS" +], AC_MSG_ERROR([need to have GiNaC installed])) + +AC_OUTPUT(Makefile) +@end example + +The only command in this which is not standard for automake +is the @samp{AM_PATH_GINAC} macro. + +That command does the following: + +@display +If a GiNaC version greater than 0.4.0 is found, adds @env{$GINACLIB_LIBS} to +@env{$LIBS} and @env{$GINACLIB_CPPFLAGS} to @env{$CPPFLAGS}. Otherwise, dies +with the error message "need to have GiNaC installed" +@end display + +And the @file{Makefile.am}, which will be used to build the Makefile. + +@example +## Process this file with automake to produce Makefile.in +bin_PROGRAMS = simple +simple_SOURCES = simple.cpp +@end example + +This @file{Makefile.am}, says that we are building a single executable, +from a single sourcefile @file{simple.cpp}. Since every program +we are building uses GiNaC we simply added the GiNaC options +to @env{$LIBS} and @env{$CPPFLAGS}, but in other circumstances, we might +want to specify them on a per-program basis: for instance by +adding the lines: + +@example +simple_LDADD = $(GINACLIB_LIBS) +INCLUDES = $(GINACLIB_CPPFLAGS) +@end example + +to the @file{Makefile.am}. + +To try this example out, create a new directory and add the three +files above to it. + +Now execute the following commands: + +@example +$ automake --add-missing +$ aclocal +$ autoconf +@end example + +You now have a package that can be built in the normal fashion + +@example +$ ./configure +$ make +$ make install +@end example + -@node Bibliography, Concept Index, Internal representation of products and sums, Top +@node Bibliography, Concept Index, Example package, Top @c node-name, next, previous, up @appendix Bibliography diff --git a/doc/tutorial/stamp-vti b/doc/tutorial/stamp-vti index e176f4cf..468f23de 100644 --- a/doc/tutorial/stamp-vti +++ b/doc/tutorial/stamp-vti @@ -1,3 +1,3 @@ -@set UPDATED 26 November 1999 +@set UPDATED 30 November 1999 @set EDITION 0.4.0 @set VERSION 0.4.0 diff --git a/doc/tutorial/version.texi b/doc/tutorial/version.texi index e176f4cf..468f23de 100644 --- a/doc/tutorial/version.texi +++ b/doc/tutorial/version.texi @@ -1,3 +1,3 @@ -@set UPDATED 26 November 1999 +@set UPDATED 30 November 1999 @set EDITION 0.4.0 @set VERSION 0.4.0 diff --git a/ginac-config.in b/ginac-config.in new file mode 100644 index 00000000..dd2fbaad --- /dev/null +++ b/ginac-config.in @@ -0,0 +1,57 @@ +#!/bin/sh + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +exec_prefix_set=no + +usage="\ +Usage: ginac-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cppflags]" + +if test $# -eq 0; then + echo "${usage}" 1>&2 + exit 1 +fi + +while test $# -gt 0; do + case "$1" in + -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + case $1 in + --prefix=*) + prefix=$optarg + if test $exec_prefix_set = no ; then + exec_prefix=$optarg + fi + ;; + --prefix) + echo $prefix + ;; + --exec-prefix=*) + exec_prefix=$optarg + exec_prefix_set=yes + ;; + --exec-prefix) + echo $exec_prefix + ;; + --version) + echo @GINACLIB_VERSION@ + ;; + --cppflags) + if test @includedir@ != /usr/include ; then + includes=-I@includedir@ + fi + echo $includes @GINACLIB_CPPFLAGS@ + ;; + --libs) + libdirs=-L@libdir@ + echo $libdirs -lginac @GINACLIB_LIBS@ + ;; + *) + echo "${usage}" 1>&2 + exit 1 + ;; + esac + shift +done diff --git a/ginac.m4 b/ginac.m4 new file mode 100644 index 00000000..ebe30299 --- /dev/null +++ b/ginac.m4 @@ -0,0 +1,166 @@ +# Configure paths for GiNaC +# Christian Bauer 12/1/99 +# stolen from Sam Lantinga +# stolen from Manish Singh +# stolen back from Frank Belew +# stolen from Manish Singh +# Shamelessly stolen from Owen Taylor + +dnl AM_PATH_GINAC([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for GiNaC, and define GINACLIB_CPPFLAGS and GINACLIB_LIBS +dnl +AC_DEFUN(AM_PATH_GINAC, +[dnl +dnl Get the cppflags and libraries from the ginac-config script +dnl +AC_ARG_WITH(ginac-prefix,[ --with-ginac-prefix=PFX Prefix where GiNaC is installed (optional)], + ginac_prefix="$withval", ginac_prefix="") +AC_ARG_WITH(ginac-exec-prefix,[ --with-ginac-exec-prefix=PFX Exec prefix where GiNaC is installed (optional)], + ginac_exec_prefix="$withval", ginac_exec_prefix="") +AC_ARG_ENABLE(ginactest, [ --disable-ginactest Do not try to compile and run a test GiNaC program], + , enable_ginactest=yes) + + if test x$ginac_exec_prefix != x ; then + ginac_args="$ginac_args --exec-prefix=$ginac_exec_prefix" + if test x${GINACLIB_CONFIG+set} != xset ; then + GINACLIB_CONFIG=$ginac_exec_prefix/bin/ginac-config + fi + fi + if test x$ginac_prefix != x ; then + ginac_args="$ginac_args --prefix=$ginac_prefix" + if test x${GINACLIB_CONFIG+set} != xset ; then + GINACLIB_CONFIG=$ginac_prefix/bin/ginac-config + fi + fi + + AC_PATH_PROG(GINACLIB_CONFIG, ginac-config, no) + min_ginac_version=ifelse([$1], ,0.4.0,$1) + AC_MSG_CHECKING(for GiNaC - version >= $min_ginac_version) + no_ginac="" + if test "$GINACLIB_CONFIG" = "no" ; then + no_ginac=yes + else + GINACLIB_CPPFLAGS=`$GINACLIB_CONFIG $ginacconf_args --cppflags` + GINACLIB_LIBS=`$GINACLIB_CONFIG $ginacconf_args --libs` + + ginac_major_version=`$GINACLIB_CONFIG $ginac_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + ginac_minor_version=`$GINACLIB_CONFIG $ginac_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + ginac_micro_version=`$GINACLIB_CONFIG $ginac_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_ginactest" = "xyes" ; then + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $GINACLIB_CPPFLAGS" + LIBS="$LIBS $GINACLIB_LIBS" +dnl +dnl Now check if the installed GiNaC is sufficiently new. (Also sanity +dnl checks the results of ginac-config to some extent +dnl + rm -f conf.ginactest + AC_TRY_RUN([ +#include +#include +#include +#include + +char* +my_strdup (char *str) +{ + char *new_str; + + if (str) + { + new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); + strcpy (new_str, str); + } + else + new_str = NULL; + + return new_str; +} + +int main () +{ + int major, minor, micro; + char *tmp_version; + + system ("touch conf.ginactest"); + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = my_strdup("$min_ginac_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_ginac_version"); + exit(1); + } + + if (($ginac_major_version > major) || + (($ginac_major_version == major) && ($ginac_minor_version > minor)) || + (($ginac_major_version == major) && ($ginac_minor_version == minor) && ($ginac_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** 'ginac-config --version' returned %d.%d.%d, but the minimum version\n", $ginac_major_version, $ginac_minor_version, $ginac_micro_version); + printf("*** of GiNaC required is %d.%d.%d. If ginac-config is correct, then it is\n", major, minor, micro); + printf("*** best to upgrade to the required version.\n"); + printf("*** If ginac-config was wrong, set the environment variable GINACLIB_CONFIG\n"); + printf("*** to point to the correct copy of ginac-config, and remove the file\n"); + printf("*** config.cache before re-running configure\n"); + return 1; + } +} + +],, no_ginac=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_ginac" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$GINACLIB_CONFIG" = "no" ; then + echo "*** The ginac-config script installed by GiNaC could not be found" + echo "*** If GiNaC was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the GINACLIB_CONFIG environment variable to the" + echo "*** full path to ginac-config." + else + if test -f conf.ginactest ; then + : + else + echo "*** Could not run GiNaC test program, checking why..." + CPPFLAGS="$CFLAGS $GINACLIB_CPPFLAGS" + LIBS="$LIBS $GINACLIB_LIBS" + AC_TRY_LINK([ +#include +#include +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding GiNaC or finding the wrong" + echo "*** version of GiNaC. If it is not finding GiNaC, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means GiNaC was incorrectly installed" + echo "*** or that you have moved GiNaC since it was installed. In the latter case, you" + echo "*** may want to edit the ginac-config script: $GINACLIB_CONFIG" ]) + CPPFLAGS="$ac_save_CPPFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + GINACLIB_CPPFLAGS="" + GINACLIB_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GINACLIB_CPPFLAGS) + AC_SUBST(GINACLIB_LIBS) + rm -f conf.ginactest +]) diff --git a/ginac/Makefile.in b/ginac/Makefile.in index 0f8ae530..0a0c3306 100644 --- a/ginac/Makefile.in +++ b/ginac/Makefile.in @@ -68,7 +68,9 @@ DOXYGEN = @DOXYGEN@ DVIPS = @DVIPS@ FIG2DEV = @FIG2DEV@ GINACLIB_BINARY_AGE = @GINACLIB_BINARY_AGE@ +GINACLIB_CPPFLAGS = @GINACLIB_CPPFLAGS@ GINACLIB_INTERFACE_AGE = @GINACLIB_INTERFACE_AGE@ +GINACLIB_LIBS = @GINACLIB_LIBS@ GINACLIB_MAJOR_VERSION = @GINACLIB_MAJOR_VERSION@ GINACLIB_MICRO_VERSION = @GINACLIB_MICRO_VERSION@ GINACLIB_MINOR_VERSION = @GINACLIB_MINOR_VERSION@ diff --git a/ginsh/Makefile.in b/ginsh/Makefile.in index 97771d05..8bb6e4f5 100644 --- a/ginsh/Makefile.in +++ b/ginsh/Makefile.in @@ -68,7 +68,9 @@ DOXYGEN = @DOXYGEN@ DVIPS = @DVIPS@ FIG2DEV = @FIG2DEV@ GINACLIB_BINARY_AGE = @GINACLIB_BINARY_AGE@ +GINACLIB_CPPFLAGS = @GINACLIB_CPPFLAGS@ GINACLIB_INTERFACE_AGE = @GINACLIB_INTERFACE_AGE@ +GINACLIB_LIBS = @GINACLIB_LIBS@ GINACLIB_MAJOR_VERSION = @GINACLIB_MAJOR_VERSION@ GINACLIB_MICRO_VERSION = @GINACLIB_MICRO_VERSION@ GINACLIB_MINOR_VERSION = @GINACLIB_MINOR_VERSION@ -- 2.44.0 From 48b41ea321ed9fa6115a1061d1a1d2f8d8ad0400 Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Wed, 1 Dec 1999 21:13:01 +0000 Subject: [PATCH 12/16] - added prefix and postfix increment and decrement operators for class numeric - made all function_index const - added overloaded psi(x) and psi(n,x) with some sensible behaviour --- ginac/function.pl | 4 ++-- ginac/inifcns.h | 4 ++-- ginac/inifcns_gamma.cpp | 40 +++++++++++++++++++++++++--------------- ginac/inifcns_zeta.cpp | 2 +- ginac/numeric.h | 3 ++- ginac/operators.cpp | 34 +++++++++++++++++++++++++++++++++- ginac/operators.h | 4 ++++ 7 files changed, 69 insertions(+), 22 deletions(-) diff --git a/ginac/function.pl b/ginac/function.pl index 06bf2d67..0e6cacfc 100755 --- a/ginac/function.pl +++ b/ginac/function.pl @@ -34,7 +34,7 @@ sub generate { $declare_function_macro=generate( <<'END_OF_DECLARE_FUNCTION_MACRO','GiNaC::ex const & p${N}','p${N}'); #define DECLARE_FUNCTION_${N}P(NAME) \\ -extern unsigned function_index_##NAME; \\ +extern const unsigned function_index_##NAME; \\ inline GiNaC::function NAME(${SEQ1}) { \\ return GiNaC::function(function_index_##NAME, ${SEQ2}); \\ } @@ -155,7 +155,7 @@ $declare_function_macro // end of generated lines #define REGISTER_FUNCTION(NAME,E,EF,D,S) \\ -unsigned function_index_##NAME=GiNaC::function::register_new(#NAME,E,EF,D,S); +const unsigned function_index_##NAME=GiNaC::function::register_new(#NAME,E,EF,D,S); #define BEGIN_TYPECHECK \\ bool automatic_typecheck=true; diff --git a/ginac/inifcns.h b/ginac/inifcns.h index 725c1ee7..8be87d64 100644 --- a/ginac/inifcns.h +++ b/ginac/inifcns.h @@ -87,11 +87,11 @@ DECLARE_FUNCTION_1P(zeta) DECLARE_FUNCTION_1P(gamma) /** Psi-function (aka polygamma-function). */ -extern unsigned function_index_psi1; +extern const unsigned function_index_psi1; inline function psi(ex const & p1) { return function(function_index_psi1, p1); } -extern unsigned function_index_psi2; +extern const unsigned function_index_psi2; inline function psi(ex const & p1, ex const & p2) { return function(function_index_psi2, p1, p2); } diff --git a/ginac/inifcns_gamma.cpp b/ginac/inifcns_gamma.cpp index a208592f..5610d48e 100644 --- a/ginac/inifcns_gamma.cpp +++ b/ginac/inifcns_gamma.cpp @@ -113,10 +113,30 @@ REGISTER_FUNCTION(gamma, gamma_eval, gamma_evalf, gamma_diff, gamma_series); static ex psi1_eval(ex const & x) { if (x.info(info_flags::numeric)) { - // do some stuff... + if (x.info(info_flags::integer) && !x.info(info_flags::positive)) + throw (std::domain_error("psi_eval(): simple pole")); + if (x.info(info_flags::positive)) { + // psi(n) -> 1 + 1/2 +...+ 1/(n-1) - EulerGamma + if (x.info(info_flags::integer)) { + numeric rat(0); + for (numeric i(ex_to_numeric(x)-numONE()); i.is_positive(); --i) + rat += i.inverse(); + return rat-EulerGamma; + } + // psi((2m+1)/2) -> 2/(2m+1) + 2/2m +...+ 2/1 - EulerGamma - 2log(2) + if ((exTWO()*x).info(info_flags::integer)) { + numeric rat(0); + for (numeric i((ex_to_numeric(x)-numONE())*numTWO()); i.is_positive(); i-=numTWO()) + rat += numTWO()*i.inverse(); + return rat-EulerGamma-exTWO()*log(exTWO()); + } + if (x.compare(exONE())==1) { + // should call numeric, since >1 + } + } } return psi(x).hold(); -} +} static ex psi1_evalf(ex const & x) { @@ -134,12 +154,7 @@ static ex psi1_diff(ex const & x, unsigned diff_param) return psi(exONE(), x); } -static ex psi1_series(ex const & x, symbol const & s, ex const & point, int order) -{ - throw(std::logic_error("Nobody told me how to series expand the psi function. :-(")); -} - -unsigned function_index_psi1 = function::register_new("psi", psi1_eval, psi1_evalf, psi1_diff, psi1_series); +const unsigned function_index_psi1 = function::register_new("psi", psi1_eval, psi1_evalf, psi1_diff, NULL); ////////// // Psi-functions (aka polygamma-functions) psi(0,x)==psi(x) @@ -151,7 +166,7 @@ static ex psi2_eval(ex const & n, ex const & x) { // psi(0,x) -> psi(x) if (n.is_zero()) - return psi(x).hold(); + return psi(x); if (n.info(info_flags::numeric) && x.info(info_flags::numeric)) { // do some stuff... } @@ -180,11 +195,6 @@ static ex psi2_diff(ex const & n, ex const & x, unsigned diff_param) return psi(n+1, x); } -static ex psi2_series(ex const & n, ex const & x, symbol const & s, ex const & point, int order) -{ - throw(std::logic_error("Nobody told me how to series expand the psi functions. :-(")); -} - -unsigned function_index_psi2 = function::register_new("psi", psi2_eval, psi2_evalf, psi2_diff, psi2_series); +const unsigned function_index_psi2 = function::register_new("psi", psi2_eval, psi2_evalf, psi2_diff, NULL); } // namespace GiNaC diff --git a/ginac/inifcns_zeta.cpp b/ginac/inifcns_zeta.cpp index 1a850ac4..cd638765 100644 --- a/ginac/inifcns_zeta.cpp +++ b/ginac/inifcns_zeta.cpp @@ -44,7 +44,7 @@ static ex zeta_eval(ex const & x) if (y.is_integer()) { if (y.is_zero()) return -exHALF(); - if (!x.compare(exONE())) + if (x.is_equal(exONE())) throw(std::domain_error("zeta(1): infinity")); if (x.info(info_flags::posint)) { if (x.info(info_flags::odd)) diff --git a/ginac/numeric.h b/ginac/numeric.h index 13c790fc..eb356590 100644 --- a/ginac/numeric.h +++ b/ginac/numeric.h @@ -317,7 +317,8 @@ inline numeric numer(numeric const & x) inline numeric denom(numeric const & x) { return x.denom(); } -ex IEvalf(void); +// numeric evaluation functions for class constant objects: + ex PiEvalf(void); ex EulerGammaEvalf(void); ex CatalanEvalf(void); diff --git a/ginac/operators.cpp b/ginac/operators.cpp index d9882c0e..4d762b30 100644 --- a/ginac/operators.cpp +++ b/ginac/operators.cpp @@ -272,7 +272,39 @@ numeric operator+(numeric const & lh) numeric operator-(numeric const & lh) { - return (numeric(-1)*lh); + return numMINUSONE()*lh; +} + +/** Numeric prefix increment. Adds 1 and returns incremented number. */ +numeric& operator++(numeric & rh) +{ + rh = rh+numONE(); + return rh; +} + +/** Numeric prefix decrement. Subtracts 1 and returns decremented number. */ +numeric& operator--(numeric & rh) +{ + rh = rh-numONE(); + return rh; +} + +/** Numeric postfix increment. Returns the number and leaves the original + * incremented by 1. */ +numeric operator++(numeric & lh, int) +{ + numeric tmp = lh; + lh = lh+numONE(); + return tmp; +} + +/** Numeric Postfix decrement. Returns the number and leaves the original + * decremented by 1. */ +numeric operator--(numeric & lh, int) +{ + numeric tmp = lh; + lh = lh-numONE(); + return tmp; } // binary relational operators ex with ex diff --git a/ginac/operators.h b/ginac/operators.h index 4c95a551..fab2870b 100644 --- a/ginac/operators.h +++ b/ginac/operators.h @@ -92,6 +92,10 @@ ex operator-(ex const & lh); numeric operator+(numeric const & lh); numeric operator-(numeric const & lh); +numeric& operator++(numeric & rh); +numeric& operator--(numeric & rh); +numeric operator++(numeric & lh, int); +numeric operator--(numeric & lh, int); // binary relational operators ex with ex relational operator==(ex const & lh, ex const & rh); -- 2.44.0 From afdd7fa8c6c0a587f7c80789198551383e8beb7b Mon Sep 17 00:00:00 2001 From: Alexander Frink Date: Thu, 2 Dec 1999 18:44:55 +0000 Subject: [PATCH 13/16] #ifndef around namespace GiNaC { } --- check/differentiation.cpp | 3 ++ check/expand_subs.cpp | 3 ++ check/inifcns_consist.cpp | 3 ++ check/lsolve_onedim.cpp | 3 ++ check/matrix_checks.cpp | 3 ++ check/normalization.cpp | 3 ++ check/numeric_consist.cpp | 3 ++ check/numeric_output.cpp | 3 ++ check/paranoia_check.cpp | 3 ++ check/poly_gcd.cpp | 3 ++ check/powerlaws.cpp | 3 ++ check/series_expansion.cpp | 3 ++ ginac/add.cpp | 4 +++ ginac/add.h | 4 +++ ginac/basic.cpp | 4 +++ ginac/basic.h | 29 ++++++++++++++- ginac/clifford.cpp | 4 +++ ginac/clifford.h | 4 +++ ginac/color.cpp | 5 +++ ginac/color.h | 4 +++ ginac/coloridx.cpp | 4 +++ ginac/coloridx.h | 4 +++ ginac/constant.cpp | 4 +++ ginac/constant.h | 4 +++ ginac/container.pl | 15 +++++++- ginac/diff.cpp | 4 +++ ginac/ex.cpp | 4 +++ ginac/ex.h | 7 +++- ginac/expair.h | 4 +++ ginac/expairseq.cpp | 4 +++ ginac/expairseq.h | 8 +++++ ginac/exprseq_suppl.cpp | 4 +++ ginac/fail.cpp | 4 +++ ginac/fail.h | 4 +++ ginac/flags.h | 4 +++ ginac/function.pl | 72 +++++++++++++++++++++++++++++++++++--- ginac/idx.cpp | 4 +++ ginac/idx.h | 8 +++-- ginac/indexed.cpp | 4 +++ ginac/indexed.h | 4 +++ ginac/inifcns.cpp | 4 +++ ginac/inifcns.h | 4 +++ ginac/inifcns_gamma.cpp | 4 +++ ginac/inifcns_trans.cpp | 4 +++ ginac/inifcns_zeta.cpp | 4 +++ ginac/isospin.cpp | 5 +++ ginac/isospin.h | 4 +++ ginac/lorentzidx.cpp | 4 +++ ginac/lorentzidx.h | 4 +++ ginac/lst_suppl.cpp | 4 +++ ginac/matrix.cpp | 4 +++ ginac/matrix.h | 4 +++ ginac/mul.cpp | 4 +++ ginac/mul.h | 4 +++ ginac/ncmul.cpp | 4 +++ ginac/ncmul.h | 4 +++ ginac/normal.cpp | 20 +++++++++++ ginac/normal.h | 4 +++ ginac/numeric.cpp | 4 +++ ginac/numeric.h | 4 +++ ginac/operators.cpp | 4 +++ ginac/operators.h | 4 +++ ginac/power.cpp | 4 +++ ginac/power.h | 4 +++ ginac/print.cpp | 4 +++ ginac/printcsrc.cpp | 4 +++ ginac/printraw.cpp | 4 +++ ginac/printtree.cpp | 4 +++ ginac/relational.cpp | 4 +++ ginac/relational.h | 4 +++ ginac/series.cpp | 5 ++- ginac/series.h | 4 +++ ginac/simp_lor.cpp | 4 +++ ginac/simp_lor.h | 4 +++ ginac/structure.cpp | 4 +++ ginac/structure.h | 4 +++ ginac/structure.pl | 8 +++++ ginac/symbol.cpp | 4 +++ ginac/symbol.h | 4 +++ ginac/tinfos.h | 4 +++ ginac/utils.cpp | 4 +++ ginac/utils.h | 4 +++ ginsh/ginsh.h | 3 ++ ginsh/ginsh_parser.yy | 5 ++- 84 files changed, 451 insertions(+), 11 deletions(-) diff --git a/check/differentiation.cpp b/check/differentiation.cpp index 0d963fed..348b5fd5 100644 --- a/check/differentiation.cpp +++ b/check/differentiation.cpp @@ -21,7 +21,10 @@ */ #include + +#ifndef NO_GINAC_NAMESPACE using namespace GiNaC; +#endif // ndef NO_GINAC_NAMESPACE static unsigned check_diff(const ex &e, const symbol &x, const ex &d, unsigned nth=1) diff --git a/check/expand_subs.cpp b/check/expand_subs.cpp index b6ff16f0..4d78708b 100644 --- a/check/expand_subs.cpp +++ b/check/expand_subs.cpp @@ -32,7 +32,10 @@ #include + +#ifndef NO_GINAC_NAMESPACE using namespace GiNaC; +#endif // ndef NO_GINAC_NAMESPACE #define VECSIZE 100 diff --git a/check/inifcns_consist.cpp b/check/inifcns_consist.cpp index cabecc6a..024dad79 100644 --- a/check/inifcns_consist.cpp +++ b/check/inifcns_consist.cpp @@ -22,7 +22,10 @@ */ #include + +#ifndef NO_GINAC_NAMESPACE using namespace GiNaC; +#endif // ndef NO_GINAC_NAMESPACE /* Simple tests on the sine trigonometric function. */ static unsigned inifcns_consist_sin(void) diff --git a/check/lsolve_onedim.cpp b/check/lsolve_onedim.cpp index 448a1637..be113c2d 100644 --- a/check/lsolve_onedim.cpp +++ b/check/lsolve_onedim.cpp @@ -22,7 +22,10 @@ */ #include + +#ifndef NO_GINAC_NAMESPACE using namespace GiNaC; +#endif // ndef NO_GINAC_NAMESPACE unsigned lsolve_onedim(void) { diff --git a/check/matrix_checks.cpp b/check/matrix_checks.cpp index 80d8bf95..3da30af8 100644 --- a/check/matrix_checks.cpp +++ b/check/matrix_checks.cpp @@ -22,7 +22,10 @@ #include #include + +#ifndef NO_GINAC_NAMESPACE using namespace GiNaC; +#endif // ndef NO_GINAC_NAMESPACE static unsigned matrix_determinants(void) { diff --git a/check/normalization.cpp b/check/normalization.cpp index 3f814fde..bf761ffe 100644 --- a/check/normalization.cpp +++ b/check/normalization.cpp @@ -21,7 +21,10 @@ */ #include + +#ifndef NO_GINAC_NAMESPACE using namespace GiNaC; +#endif // ndef NO_GINAC_NAMESPACE static symbol x("x"), y("y"), z("z"); diff --git a/check/numeric_consist.cpp b/check/numeric_consist.cpp index 6c5fd6be..d6a3ffca 100644 --- a/check/numeric_consist.cpp +++ b/check/numeric_consist.cpp @@ -23,7 +23,10 @@ #include #include + +#ifndef NO_GINAC_NAMESPACE using namespace GiNaC; +#endif // ndef NO_GINAC_NAMESPACE /* Simple and maybe somewhat pointless consistency tests of assorted tests and * conversions. */ diff --git a/check/numeric_output.cpp b/check/numeric_output.cpp index 99f3afdc..50dd8c1f 100644 --- a/check/numeric_output.cpp +++ b/check/numeric_output.cpp @@ -21,7 +21,10 @@ */ #include + +#ifndef NO_GINAC_NAMESPACE using namespace GiNaC; +#endif // ndef NO_GINAC_NAMESPACE unsigned numeric_output(void) { diff --git a/check/paranoia_check.cpp b/check/paranoia_check.cpp index d84946f2..b42225ca 100644 --- a/check/paranoia_check.cpp +++ b/check/paranoia_check.cpp @@ -24,7 +24,10 @@ */ #include + +#ifndef NO_GINAC_NAMESPACE using namespace GiNaC; +#endif // ndef NO_GINAC_NAMESPACE // The very first pair of historic problems had its roots in power.cpp and was // finally resolved on April 27th. (Fixing the first on April 23rd actually diff --git a/check/poly_gcd.cpp b/check/poly_gcd.cpp index 484eb2d2..1448ae3c 100644 --- a/check/poly_gcd.cpp +++ b/check/poly_gcd.cpp @@ -22,7 +22,10 @@ */ #include + +#ifndef NO_GINAC_NAMESPACE using namespace GiNaC; +#endif // ndef NO_GINAC_NAMESPACE const int MAX_VARIABLES = 5; diff --git a/check/powerlaws.cpp b/check/powerlaws.cpp index c51bff8e..b7fdd60c 100644 --- a/check/powerlaws.cpp +++ b/check/powerlaws.cpp @@ -22,7 +22,10 @@ */ #include + +#ifndef NO_GINAC_NAMESPACE using namespace GiNaC; +#endif // ndef NO_GINAC_NAMESPACE static unsigned powerlaws1(void) { diff --git a/check/series_expansion.cpp b/check/series_expansion.cpp index 292f5b92..b648f9d7 100644 --- a/check/series_expansion.cpp +++ b/check/series_expansion.cpp @@ -21,7 +21,10 @@ */ #include + +#ifndef NO_GINAC_NAMESPACE using namespace GiNaC; +#endif // ndef NO_GINAC_NAMESPACE static symbol x("x"); diff --git a/ginac/add.cpp b/ginac/add.cpp index 6f5380cc..553b8272 100644 --- a/ginac/add.cpp +++ b/ginac/add.cpp @@ -27,7 +27,9 @@ #include "mul.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -653,4 +655,6 @@ unsigned add::precedence=40; const add some_add; type_info const & typeid_add=typeid(some_add); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/add.h b/ginac/add.h index 37d502a0..1acb03d1 100644 --- a/ginac/add.h +++ b/ginac/add.h @@ -25,7 +25,9 @@ #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** Sum of expressions. */ class add : public expairseq @@ -112,6 +114,8 @@ inline const add &ex_to_add(const ex &e) return static_cast(*e.bp); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_ADD_H__ diff --git a/ginac/basic.cpp b/ginac/basic.cpp index eb4a72e0..96fa259d 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -34,7 +34,9 @@ #include "utils.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -417,4 +419,6 @@ type_info const & typeid_basic=typeid(some_basic); int max_recursion_level=1024; +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/basic.h b/ginac/basic.h index a0e3f6ed..ae810476 100644 --- a/ginac/basic.h +++ b/ginac/basic.h @@ -27,11 +27,16 @@ #include #include +// CINT needs to work properly with +#include + #include #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE class basic; class ex; @@ -39,7 +44,8 @@ class symbol; class lst; class numeric; -typedef vector exvector; +//typedef vector exvector; +typedef vector exvector; // CINT does not like vector<...,default_alloc> #define INLINE_BASIC_CONSTRUCTORS @@ -180,6 +186,8 @@ extern int max_recursion_level; // convenience macros +#ifndef NO_GINAC_NAMESPACE + #define is_of_type(OBJ,TYPE) \ (dynamic_cast(const_cast(&OBJ))!=0) @@ -192,6 +200,25 @@ extern int max_recursion_level; #define is_ex_exactly_of_type(OBJ,TYPE) \ ((*(OBJ).bp).tinfo()==GiNaC::TINFO_##TYPE) +#else // ndef NO_GINAC_NAMESPACE + +#define is_of_type(OBJ,TYPE) \ + (dynamic_cast(const_cast(&OBJ))!=0) + +#define is_exactly_of_type(OBJ,TYPE) \ + ((OBJ).tinfo()==TINFO_##TYPE) + +#define is_ex_of_type(OBJ,TYPE) \ + (dynamic_cast(const_cast((OBJ).bp))!=0) + +#define is_ex_exactly_of_type(OBJ,TYPE) \ + ((*(OBJ).bp).tinfo()==TINFO_##TYPE) + +#endif // ndef NO_GINAC_NAMESPACE + +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_BASIC_H__ + diff --git a/ginac/clifford.cpp b/ginac/clifford.cpp index 16f9a4d4..ff98011f 100644 --- a/ginac/clifford.cpp +++ b/ginac/clifford.cpp @@ -29,7 +29,9 @@ #include "utils.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -211,4 +213,6 @@ unsigned clifford::next_serial=0; const clifford some_clifford; type_info const & typeid_clifford=typeid(some_clifford); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/clifford.h b/ginac/clifford.h index 49a3613b..3302f461 100644 --- a/ginac/clifford.h +++ b/ginac/clifford.h @@ -27,7 +27,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** Base class for clifford object */ class clifford : public indexed @@ -90,6 +92,8 @@ inline const clifford &ex_to_clifford(const ex &e) return static_cast(*e.bp); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_CLIFFORD_H__ diff --git a/ginac/color.cpp b/ginac/color.cpp index 095a3b0c..468645dd 100644 --- a/ginac/color.cpp +++ b/ginac/color.cpp @@ -35,7 +35,9 @@ #include "relational.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -965,4 +967,7 @@ void append_exvector_to_exvector(exvector & dest, exvector const & source) } } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE + diff --git a/ginac/color.h b/ginac/color.h index 9967f451..f72034d8 100644 --- a/ginac/color.h +++ b/ginac/color.h @@ -28,7 +28,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE const unsigned MAX_REPRESENTATION_LABELS = 4; const unsigned COLOR_EIGHT = 8; // N*N-1 @@ -162,6 +164,8 @@ ex brute_force_sum_color_indices(ex const & e); void append_exvector_to_exvector(exvector & dest, exvector const & source); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_COLOR_H__ diff --git a/ginac/coloridx.cpp b/ginac/coloridx.cpp index dc8eed7d..383e8bb0 100644 --- a/ginac/coloridx.cpp +++ b/ginac/coloridx.cpp @@ -26,7 +26,9 @@ #include "utils.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -213,4 +215,6 @@ bool coloridx::info(unsigned inf) const const coloridx some_coloridx; type_info const & typeid_coloridx=typeid(some_coloridx); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/coloridx.h b/ginac/coloridx.h index 7861c899..105f4a35 100644 --- a/ginac/coloridx.h +++ b/ginac/coloridx.h @@ -28,7 +28,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE class coloridx : public idx { @@ -82,6 +84,8 @@ inline const coloridx &ex_to_coloridx(const ex &e) return static_cast(*e.bp); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_COLORIDX_H__ diff --git a/ginac/constant.cpp b/ginac/constant.cpp index f21c05e8..12e9dde4 100644 --- a/ginac/constant.cpp +++ b/ginac/constant.cpp @@ -28,7 +28,9 @@ #include "ex.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -165,4 +167,6 @@ const constant EulerGamma("EulerGamma", EulerGammaEvalf); * Diverts straight into CLN for evalf(). */ const constant Catalan("Catalan", CatalanEvalf); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/constant.h b/ginac/constant.h index 89cb7eba..04fdc50a 100644 --- a/ginac/constant.h +++ b/ginac/constant.h @@ -26,7 +26,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** This class holds constants, symbols with specific numerical value. Each * object of this class must either provide their own function to evaluate it @@ -90,6 +92,8 @@ extern const constant Pi; extern const constant Catalan; extern const constant EulerGamma; +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_CONSTANT_H__ diff --git a/ginac/container.pl b/ginac/container.pl index 798d6868..02893995 100755 --- a/ginac/container.pl +++ b/ginac/container.pl @@ -123,12 +123,19 @@ $interface=< + +// CINT needs to work properly with and +#include + #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE -typedef ${STLHEADER} ${STLT}; +// typedef ${STLHEADER} ${STLT}; +typedef ${STLHEADER} ${STLT}; // CINT does not like ${STLHEADER}<...,default_alloc> class ${CONTAINER} : public basic { @@ -223,7 +230,9 @@ inline const ${CONTAINER} &ex_to_${CONTAINER}(const ex &e) return static_cast(*e.bp); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_${CONTAINER_UC}_H__ @@ -269,7 +278,9 @@ $implementation=< #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE class ex; class expand_options; @@ -36,7 +38,7 @@ class status_flags; class symbol; class lst; -typedef vector exvector; +// typedef vector exvector; // enum definitions @@ -284,6 +286,9 @@ inline ex subs(ex const & thisex, lst const & ls, lst const & lr) inline void swap(ex & e1, ex & e2) { e1.swap(e2); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_EX_H__ + diff --git a/ginac/expair.h b/ginac/expair.h index 320de73e..b130465b 100644 --- a/ginac/expair.h +++ b/ginac/expair.h @@ -26,7 +26,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** A pair of expressions. * This similar to, but slightly extended STL's pair<> but we need to account @@ -197,6 +199,8 @@ public: } }; +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_EXPAIR_H__ diff --git a/ginac/expairseq.cpp b/ginac/expairseq.cpp index 360c7b97..2e50b0e4 100644 --- a/ginac/expairseq.cpp +++ b/ginac/expairseq.cpp @@ -29,7 +29,9 @@ #include "debugmsg.h" #include "utils.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE #ifdef EXPAIRSEQ_USE_HASHTAB #error "FIXME: expair_needs_further_processing not yet implemented for hashtabs, sorry. A.F." @@ -1627,4 +1629,6 @@ unsigned expairseq::hashtabfactor=1; const expairseq some_expairseq; type_info const & typeid_expairseq=typeid(some_expairseq); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/expairseq.h b/ginac/expairseq.h index a14cecaa..72ac829c 100644 --- a/ginac/expairseq.h +++ b/ginac/expairseq.h @@ -25,9 +25,15 @@ #include #include + +// CINT needs to work properly with and +//#include + #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE //#define EXPAIRSEQ_USE_HASHTAB @@ -194,6 +200,8 @@ inline const expairseq &ex_to_expairseq(const ex &e) return static_cast(*e.bp); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_EXPAIRSEQ_H__ diff --git a/ginac/exprseq_suppl.cpp b/ginac/exprseq_suppl.cpp index 8ac31b8b..ef5f1c5b 100644 --- a/ginac/exprseq_suppl.cpp +++ b/ginac/exprseq_suppl.cpp @@ -24,7 +24,9 @@ #include "exprseq.h" #include "ex.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE bool exprseq::info(unsigned inf) const { @@ -40,4 +42,6 @@ ex & exprseq::let_op(int const i) return seq[i]; } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/fail.cpp b/ginac/fail.cpp index e5800a38..d4997196 100644 --- a/ginac/fail.cpp +++ b/ginac/fail.cpp @@ -24,7 +24,9 @@ #include "fail.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -123,4 +125,6 @@ int fail::compare_same_type(basic const & other) const const fail some_fail; type_info const & typeid_fail=typeid(some_fail); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/fail.h b/ginac/fail.h index 7edc7b1b..292bf797 100644 --- a/ginac/fail.h +++ b/ginac/fail.h @@ -26,7 +26,9 @@ #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE class fail : public basic { @@ -69,6 +71,8 @@ protected: extern const fail some_fail; extern type_info const & typeid_fail; +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_FAIL_H__ diff --git a/ginac/flags.h b/ginac/flags.h index 90f4e38d..6a1bfa4d 100644 --- a/ginac/flags.h +++ b/ginac/flags.h @@ -23,7 +23,9 @@ #ifndef __GINAC_FLAGS_H__ #define __GINAC_FLAGS_H__ +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE class expand_options { public: @@ -114,6 +116,8 @@ public: }; }; +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_FLAGS_H__ diff --git a/ginac/function.pl b/ginac/function.pl index 0e6cacfc..6493042b 100755 --- a/ginac/function.pl +++ b/ginac/function.pl @@ -31,15 +31,25 @@ sub generate { return $res; } -$declare_function_macro=generate( - <<'END_OF_DECLARE_FUNCTION_MACRO','GiNaC::ex const & p${N}','p${N}'); +$declare_function_macro_namespace=generate( + <<'END_OF_DECLARE_FUNCTION_MACRO_NAMESPACE','GiNaC::ex const & p${N}','p${N}'); #define DECLARE_FUNCTION_${N}P(NAME) \\ extern const unsigned function_index_##NAME; \\ inline GiNaC::function NAME(${SEQ1}) { \\ return GiNaC::function(function_index_##NAME, ${SEQ2}); \\ } -END_OF_DECLARE_FUNCTION_MACRO +END_OF_DECLARE_FUNCTION_MACRO_NAMESPACE + +$declare_function_macro_no_namespace=generate( + <<'END_OF_DECLARE_FUNCTION_MACRO_NO_NAMESPACE','ex const & p${N}','p${N}'); +#define DECLARE_FUNCTION_${N}P(NAME) \\ +extern unsigned function_index_##NAME; \\ +inline function NAME(${SEQ1}) { \\ + return function(function_index_##NAME, ${SEQ2}); \\ +} + +END_OF_DECLARE_FUNCTION_MACRO_NO_NAMESPACE $typedef_eval_funcp=generate( 'typedef ex (* eval_funcp_${N})(${SEQ1});'."\n", @@ -148,15 +158,40 @@ $interface=< #include + +#ifdef __CINT__ +// CINT needs to work properly with +#include +#endif // def __CINT__ + #include +#ifndef NO_GINAC_NAMESPACE + // the following lines have been generated for max. ${maxargs} parameters -$declare_function_macro +$declare_function_macro_namespace // end of generated lines +#else // ndef NO_GINAC_NAMESPACE + +// the following lines have been generated for max. ${maxargs} parameters +$declare_function_macro_no_namespace +// end of generated lines + +#endif // ndef NO_GINAC_NAMESPACE + +#ifndef NO_GINAC_NAMESPACE + #define REGISTER_FUNCTION(NAME,E,EF,D,S) \\ + const unsigned function_index_##NAME=GiNaC::function::register_new(#NAME,E,EF,D,S); +#else // ndef NO_GINAC_NAMESPACE + +const unsigned function_index_##NAME=function::register_new(#NAME,E,EF,D,S); + +#endif // ndef NO_GINAC_NAMESPACE + #define BEGIN_TYPECHECK \\ bool automatic_typecheck=true; @@ -165,18 +200,31 @@ if (!is_ex_exactly_of_type(VAR,TYPE)) { \\ automatic_typecheck=false; \\ } else +#ifndef NO_GINAC_NAMESPACE + #define TYPECHECK_INTEGER(VAR) \\ if (!(VAR).info(GiNaC::info_flags::integer)) { \\ automatic_typecheck=false; \\ } else +#else // ndef NO_GINAC_NAMESPACE + +#define TYPECHECK_INTEGER(VAR) \\ +if (!(VAR).info(info_flags::integer)) { \\ + automatic_typecheck=false; \\ +} else + +#endif // ndef NO_GINAC_NAMESPACE + #define END_TYPECHECK(RV) \\ {} \\ if (!automatic_typecheck) { \\ return RV.hold(); \\ } +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE class function; @@ -206,6 +254,7 @@ struct registered_function_info { and user defined functions */ class function : public exprseq { + // CINT has a linking problem friend void ginsh_get_ginac_functions(void); // member functions @@ -271,15 +320,26 @@ protected: // utility macros +#ifndef NO_GINAC_NAMESPACE + #define is_ex_the_function(OBJ, FUNCNAME) \\ (is_ex_exactly_of_type(OBJ, function) && static_cast(OBJ.bp)->getserial() == function_index_##FUNCNAME) +#else // ndef NO_GINAC_NAMESPACE + +#define is_ex_the_function(OBJ, FUNCNAME) \\ + (is_ex_exactly_of_type(OBJ, function) && static_cast(OBJ.bp)->getserial() == function_index_##FUNCNAME) + +#endif // ndef NO_GINAC_NAMESPACE + // global constants extern const function some_function; extern type_info const & typeid_function; +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_FUNCTION_H__ @@ -319,7 +379,9 @@ $implementation=< -#include +//#include #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE class idx : public basic { @@ -100,7 +102,7 @@ inline const idx &ex_to_idx(const ex &e) // global functions -typedef vector exvector; +// typedef vector exvector; int canonicalize_indices(exvector & iv, bool antisymmetric=false); exvector idx_intersect(exvector const & iv1, exvector const & iv2); @@ -111,6 +113,8 @@ ex subs_indices(ex const & e, exvector const & idxv_contra, exvector const & idxv_co); unsigned count_index(ex const & e, ex const & i); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_IDX_H__ diff --git a/ginac/indexed.cpp b/ginac/indexed.cpp index 6e36eb30..0364d997 100644 --- a/ginac/indexed.cpp +++ b/ginac/indexed.cpp @@ -27,7 +27,9 @@ #include "idx.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -292,4 +294,6 @@ bool indexed::all_of_type_idx(void) const const indexed some_indexed; type_info const & typeid_indexed=typeid(some_indexed); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/indexed.h b/ginac/indexed.h index 3707e629..a731769b 100644 --- a/ginac/indexed.h +++ b/ginac/indexed.h @@ -26,7 +26,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** Base class for non-commutative indexed objects */ class indexed : public exprseq @@ -94,6 +96,8 @@ inline const indexed &ex_to_indexed(const ex &e) return static_cast(*e.bp); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_INDEXED_H__ diff --git a/ginac/inifcns.cpp b/ginac/inifcns.cpp index 3f67d848..25eaae0d 100644 --- a/ginac/inifcns.cpp +++ b/ginac/inifcns.cpp @@ -36,7 +36,9 @@ #include "series.h" #include "symbol.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // dilogarithm @@ -252,4 +254,6 @@ ex ncpower(ex const &basis, unsigned exponent) unsigned force_include_gamma = function_index_gamma; unsigned force_include_zeta = function_index_zeta; +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/inifcns.h b/ginac/inifcns.h index 8be87d64..84e0dbcb 100644 --- a/ginac/inifcns.h +++ b/ginac/inifcns.h @@ -26,7 +26,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** Sine. */ DECLARE_FUNCTION_1P(sin) @@ -116,6 +118,8 @@ inline bool is_order_function(ex const & e) return is_ex_the_function(e, Order); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_INIFCNS_H__ diff --git a/ginac/inifcns_gamma.cpp b/ginac/inifcns_gamma.cpp index 5610d48e..2fd58cce 100644 --- a/ginac/inifcns_gamma.cpp +++ b/ginac/inifcns_gamma.cpp @@ -31,7 +31,9 @@ #include "power.h" #include "symbol.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // Gamma-function @@ -197,4 +199,6 @@ static ex psi2_diff(ex const & n, ex const & x, unsigned diff_param) const unsigned function_index_psi2 = function::register_new("psi", psi2_eval, psi2_evalf, psi2_diff, NULL); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/inifcns_trans.cpp b/ginac/inifcns_trans.cpp index db502ca9..01711a7f 100644 --- a/ginac/inifcns_trans.cpp +++ b/ginac/inifcns_trans.cpp @@ -30,7 +30,9 @@ #include "numeric.h" #include "power.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // exponential function @@ -740,4 +742,6 @@ static ex atanh_diff(ex const & x, unsigned diff_param) REGISTER_FUNCTION(atanh, atanh_eval, atanh_evalf, atanh_diff, NULL); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/inifcns_zeta.cpp b/ginac/inifcns_zeta.cpp index cd638765..c2a298a9 100644 --- a/ginac/inifcns_zeta.cpp +++ b/ginac/inifcns_zeta.cpp @@ -30,7 +30,9 @@ #include "power.h" #include "symbol.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // Riemann's Zeta-function @@ -85,4 +87,6 @@ static ex zeta_series(ex const & x, symbol const & s, ex const & point, int orde REGISTER_FUNCTION(zeta, zeta_eval, zeta_evalf, zeta_diff, zeta_series); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/isospin.cpp b/ginac/isospin.cpp index e5288e9c..8b80a97c 100644 --- a/ginac/isospin.cpp +++ b/ginac/isospin.cpp @@ -29,7 +29,9 @@ #include "utils.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -211,4 +213,7 @@ unsigned isospin::next_serial=0; const isospin some_isospin; type_info const & typeid_isospin=typeid(some_isospin); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE + diff --git a/ginac/isospin.h b/ginac/isospin.h index c4d23864..0d25a2a9 100644 --- a/ginac/isospin.h +++ b/ginac/isospin.h @@ -26,7 +26,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** Base class for isospin object */ class isospin : public indexed @@ -89,6 +91,8 @@ inline const isospin &ex_to_isospin(const ex &e) return static_cast(*e.bp); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_ISOSPIN_H__ diff --git a/ginac/lorentzidx.cpp b/ginac/lorentzidx.cpp index 6d09ee1f..62b01aa4 100644 --- a/ginac/lorentzidx.cpp +++ b/ginac/lorentzidx.cpp @@ -26,7 +26,9 @@ #include "utils.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -251,4 +253,6 @@ lorentzidx lorentzidx::create_anonymous_representative(void) const const lorentzidx some_lorentzidx; type_info const & typeid_lorentzidx=typeid(some_lorentzidx); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/lorentzidx.h b/ginac/lorentzidx.h index 1a429021..260296ef 100644 --- a/ginac/lorentzidx.h +++ b/ginac/lorentzidx.h @@ -27,7 +27,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE class lorentzidx : public idx { @@ -89,6 +91,8 @@ inline const lorentzidx &ex_to_lorentzidx(const ex &e) return static_cast(*e.bp); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_LORENTZIDX_H__ diff --git a/ginac/lst_suppl.cpp b/ginac/lst_suppl.cpp index 927a503c..67c7e5be 100644 --- a/ginac/lst_suppl.cpp +++ b/ginac/lst_suppl.cpp @@ -23,7 +23,9 @@ #include "lst.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE bool lst::info(unsigned inf) const { @@ -31,4 +33,6 @@ bool lst::info(unsigned inf) const return basic::info(inf); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/matrix.cpp b/ginac/matrix.cpp index bacacad8..43288df4 100644 --- a/ginac/matrix.cpp +++ b/ginac/matrix.cpp @@ -26,7 +26,9 @@ #include "matrix.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor, assignment operator @@ -872,4 +874,6 @@ int matrix::pivot(int ro) const matrix some_matrix; type_info const & typeid_matrix=typeid(some_matrix); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/matrix.h b/ginac/matrix.h index 769647ca..4ad11ea8 100644 --- a/ginac/matrix.h +++ b/ginac/matrix.h @@ -27,7 +27,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** Symbolic matrices. */ class matrix : public basic @@ -152,6 +154,8 @@ inline const matrix &ex_to_matrix(const ex &e) return static_cast(*e.bp); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_MATRIX_H__ diff --git a/ginac/mul.cpp b/ginac/mul.cpp index 78f2bd9e..9155b1a9 100644 --- a/ginac/mul.cpp +++ b/ginac/mul.cpp @@ -28,7 +28,9 @@ #include "power.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -1014,4 +1016,6 @@ unsigned mul::precedence=50; const mul some_mul; type_info const & typeid_mul=typeid(some_mul); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/mul.h b/ginac/mul.h index 19dad491..76546eb0 100644 --- a/ginac/mul.h +++ b/ginac/mul.h @@ -25,7 +25,9 @@ #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** Product of expressions. */ class mul : public expairseq @@ -119,6 +121,8 @@ inline const mul &ex_to_mul(const ex &e) return static_cast(*e.bp); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_MUL_H__ diff --git a/ginac/ncmul.cpp b/ginac/ncmul.cpp index 515a870c..9e14edc0 100644 --- a/ginac/ncmul.cpp +++ b/ginac/ncmul.cpp @@ -30,7 +30,9 @@ #include "mul.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -591,4 +593,6 @@ ex simplified_ncmul(exvector const & v) status_flags::evaluated); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/ncmul.h b/ginac/ncmul.h index 03b47ca7..de48b59e 100644 --- a/ginac/ncmul.h +++ b/ginac/ncmul.h @@ -25,7 +25,9 @@ #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** Non-commutative product of expressions. */ class ncmul : public exprseq @@ -114,6 +116,8 @@ inline const ncmul &ex_to_ncmul(const ex &e) return static_cast (*e.bp); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_NCMUL_H__ diff --git a/ginac/normal.cpp b/ginac/normal.cpp index 391b80b6..3846f408 100644 --- a/ginac/normal.cpp +++ b/ginac/normal.cpp @@ -46,7 +46,9 @@ #include "series.h" #include "symbol.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE // If comparing expressions (ex::compare()) is fast, you can set this to 1. // Some routines like quo(), rem() and gcd() will then return a quick answer @@ -908,7 +910,11 @@ ex basic::smod(const numeric &xi) const ex numeric::smod(const numeric &xi) const { +#ifndef NO_GINAC_NAMESPACE return GiNaC::smod(*this, xi); +#else // ndef NO_GINAC_NAMESPACE + return ::smod(*this, xi); +#endif // ndef NO_GINAC_NAMESPACE } ex add::smod(const numeric &xi) const @@ -919,13 +925,21 @@ ex add::smod(const numeric &xi) const epvector::const_iterator itend = seq.end(); while (it != itend) { GINAC_ASSERT(!is_ex_exactly_of_type(it->rest,numeric)); +#ifndef NO_GINAC_NAMESPACE numeric coeff = GiNaC::smod(ex_to_numeric(it->coeff), xi); +#else // ndef NO_GINAC_NAMESPACE + numeric coeff = ::smod(ex_to_numeric(it->coeff), xi); +#endif // ndef NO_GINAC_NAMESPACE if (!coeff.is_zero()) newseq.push_back(expair(it->rest, coeff)); it++; } GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); +#ifndef NO_GINAC_NAMESPACE numeric coeff = GiNaC::smod(ex_to_numeric(overall_coeff), xi); +#else // ndef NO_GINAC_NAMESPACE + numeric coeff = ::smod(ex_to_numeric(overall_coeff), xi); +#endif // ndef NO_GINAC_NAMESPACE return (new add(newseq,coeff))->setflag(status_flags::dynallocated); } @@ -941,7 +955,11 @@ ex mul::smod(const numeric &xi) const #endif // def DO_GINAC_ASSERT mul * mulcopyp=new mul(*this); GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); +#ifndef NO_GINAC_NAMESPACE mulcopyp->overall_coeff = GiNaC::smod(ex_to_numeric(overall_coeff),xi); +#else // ndef NO_GINAC_NAMESPACE + mulcopyp->overall_coeff = ::smod(ex_to_numeric(overall_coeff),xi); +#endif // ndef NO_GINAC_NAMESPACE mulcopyp->clearflag(status_flags::evaluated); mulcopyp->clearflag(status_flags::hash_calculated); return mulcopyp->setflag(status_flags::dynallocated); @@ -1484,4 +1502,6 @@ ex ex::normal(int level) const return e; } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/normal.h b/ginac/normal.h index 0fa3a441..6395ffe8 100644 --- a/ginac/normal.h +++ b/ginac/normal.h @@ -24,7 +24,9 @@ #ifndef __GINAC_NORMAL_H__ #define __GINAC_NORMAL_H__ +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE class ex; class symbol; @@ -50,6 +52,8 @@ extern ex lcm(const ex &a, const ex &b, bool check_args = true); // Square-free factorization of a polynomial a(x) extern ex sqrfree(const ex &a, const symbol &x); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_NORMAL_H__ diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp index 1cc1fa69..4ab0c175 100644 --- a/ginac/numeric.cpp +++ b/ginac/numeric.cpp @@ -40,7 +40,9 @@ #include #endif +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE // linker has no problems finding text symbols for numerator or denominator //#define SANE_LINKER @@ -1453,4 +1455,6 @@ bool _numeric_digits::too_late = false; * assignment from C++ unsigned ints and evaluated like any built-in type. */ _numeric_digits Digits; +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/numeric.h b/ginac/numeric.h index eb356590..b7acbcea 100644 --- a/ginac/numeric.h +++ b/ginac/numeric.h @@ -30,7 +30,9 @@ class cl_N; // We want to include cln.h only in numeric.cpp in order to // avoid namespace pollution and keep compile-time low. +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE #define HASHVALUE_NUMERIC 0x80000001U @@ -329,6 +331,8 @@ inline const numeric &ex_to_numeric(const ex &e) return static_cast(*e.bp); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_NUMERIC_H__ diff --git a/ginac/operators.cpp b/ginac/operators.cpp index 4d762b30..c21e0ea6 100644 --- a/ginac/operators.cpp +++ b/ginac/operators.cpp @@ -31,7 +31,9 @@ #include "relational.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE // binary arithmetic operators ex with ex @@ -438,4 +440,6 @@ istream & operator>>(istream & is, ex & e) throw(std::logic_error("input from streams not yet implemented")); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/operators.h b/ginac/operators.h index fab2870b..01210fc1 100644 --- a/ginac/operators.h +++ b/ginac/operators.h @@ -25,7 +25,9 @@ #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE class ex; class numeric; @@ -129,6 +131,8 @@ relational operator>=(numeric const & lh, ex const & rh); ostream & operator<<(ostream & os, ex const & e); istream & operator>>(istream & is, ex & e); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_OPERATORS_H__ diff --git a/ginac/power.cpp b/ginac/power.cpp index bed6ed2f..64dd1fdc 100644 --- a/ginac/power.cpp +++ b/ginac/power.cpp @@ -33,7 +33,9 @@ #include "symbol.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE typedef vector intvector; @@ -721,4 +723,6 @@ unsigned power::precedence=60; const power some_power; type_info const & typeid_power=typeid(some_power); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/power.h b/ginac/power.h index 3d9ae574..25f4f8d7 100644 --- a/ginac/power.h +++ b/ginac/power.h @@ -26,7 +26,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE class numeric; class add; @@ -125,6 +127,8 @@ inline ex pow(ex const & b, ex const & e) inline ex sqrt(ex const & a) { return power(a,exHALF()); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_POWER_H__ diff --git a/ginac/print.cpp b/ginac/print.cpp index f90a40ce..c1e9841c 100644 --- a/ginac/print.cpp +++ b/ginac/print.cpp @@ -41,7 +41,9 @@ #include "symbol.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE void ex::print(ostream & os, unsigned upper_precedence) const { @@ -259,4 +261,6 @@ void matrix::print(ostream & os, unsigned upper_precedence) const os << m[row*col-1] << "]] ]]"; } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/printcsrc.cpp b/ginac/printcsrc.cpp index 2d0ccfd3..723b862b 100644 --- a/ginac/printcsrc.cpp +++ b/ginac/printcsrc.cpp @@ -39,7 +39,9 @@ #include "symbol.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** Print expression as a C++ statement. The output looks like * " = ;". The "type" parameter has an effect @@ -330,4 +332,6 @@ void relational::printcsrc(ostream & os, unsigned type, unsigned upper_precedenc os << ")"; } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/printraw.cpp b/ginac/printraw.cpp index 31f56065..331622a7 100644 --- a/ginac/printraw.cpp +++ b/ginac/printraw.cpp @@ -45,7 +45,9 @@ #include "symbol.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE void ex::printraw(ostream & os) const { @@ -225,4 +227,6 @@ void matrix::printraw(ostream & os) const os << m[row*col-1] << "))"; } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/printtree.cpp b/ginac/printtree.cpp index 99cf56e0..645799e1 100644 --- a/ginac/printtree.cpp +++ b/ginac/printtree.cpp @@ -40,7 +40,9 @@ #include "symbol.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE void ex::printtree(ostream & os, unsigned indent) const { @@ -181,4 +183,6 @@ void expairseq::printtree(ostream & os, unsigned indent) const #endif // def EXPAIRSEQ_USE_HASHTAB } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/relational.cpp b/ginac/relational.cpp index 76652e98..76bd7da2 100644 --- a/ginac/relational.cpp +++ b/ginac/relational.cpp @@ -26,7 +26,9 @@ #include "numeric.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -264,4 +266,6 @@ unsigned relational::precedence=20; const relational some_relational; type_info const & typeid_relational=typeid(some_relational); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/relational.h b/ginac/relational.h index 7426e19e..2767c89b 100644 --- a/ginac/relational.h +++ b/ginac/relational.h @@ -26,7 +26,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** This class holds a relation consisting of two expressions and a logical * relation between them. */ @@ -103,6 +105,8 @@ inline const relational &ex_to_relational(const ex &e) return static_cast(*e.bp); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_RELATIONAL_H__ diff --git a/ginac/series.cpp b/ginac/series.cpp index a390dd15..7f8d3928 100644 --- a/ginac/series.cpp +++ b/ginac/series.cpp @@ -30,8 +30,9 @@ #include "symbol.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { - +#endif // ndef NO_GINAC_NAMESPACE /* * Default constructor, destructor, copy constructor, assignment operator and helpers @@ -636,4 +637,6 @@ ex ex::series(symbol const &s, ex const &point, int order) const const series some_series; type_info const & typeid_series = typeid(some_series); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/series.h b/ginac/series.h index 5df4d822..08f859ff 100644 --- a/ginac/series.h +++ b/ginac/series.h @@ -26,7 +26,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** This class holds a extended truncated power series (positive and negative * integer powers). It consists of expression coefficients (only non-zero @@ -113,6 +115,8 @@ inline ex series_to_poly(const ex &e) return (static_cast(*e.bp).convert_to_poly(true)); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_SERIES_H__ diff --git a/ginac/simp_lor.cpp b/ginac/simp_lor.cpp index 05f96ae1..a102b74e 100644 --- a/ginac/simp_lor.cpp +++ b/ginac/simp_lor.cpp @@ -34,7 +34,9 @@ #include "symbol.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -513,4 +515,6 @@ spmapkey scalar_products::make_key(simp_lor const & v1, simp_lor const & v2) return spmapkey(strstrpair(v1.name,v2.name),anon); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/simp_lor.h b/ginac/simp_lor.h index 643a6d91..44543fc8 100644 --- a/ginac/simp_lor.h +++ b/ginac/simp_lor.h @@ -31,7 +31,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE typedef pair strstrpair; typedef pair spmapkey; @@ -170,6 +172,8 @@ ex simplify_simp_lor_mul(ex const & m, scalar_products const & sp); ex simplify_simp_lor(ex const & e, scalar_products const & sp); ex Dim(void); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef _SIMP__GINAC_LOR_H__ diff --git a/ginac/structure.cpp b/ginac/structure.cpp index 539eaf76..76ee847d 100644 --- a/ginac/structure.cpp +++ b/ginac/structure.cpp @@ -25,7 +25,9 @@ #include "structure.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -175,4 +177,6 @@ unsigned structure::register_new(char const * nm) const structure some_structure; type_info const & typeid_structure=typeid(some_structure); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/structure.h b/ginac/structure.h index 34788875..abde78d7 100644 --- a/ginac/structure.h +++ b/ginac/structure.h @@ -25,7 +25,9 @@ #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE struct registered_structure_info { char const * name; @@ -84,6 +86,8 @@ public: extern const structure some_structure; extern type_info const & typeid_structure; +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_STRUCTURE_H__ diff --git a/ginac/structure.pl b/ginac/structure.pl index 2ae1625a..d26f78a8 100755 --- a/ginac/structure.pl +++ b/ginac/structure.pl @@ -150,7 +150,9 @@ ${input_structure} #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE class ${STRUCTURE} : public structure { @@ -215,7 +217,9 @@ extern const unsigned tinfo_${STRUCTURE}; #define ex_to_${STRUCTURE}(X) (static_cast<${STRUCTURE} const &>(*(X).bp)) +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef _${STRUCTURE_UC}_H_ @@ -254,7 +258,9 @@ ${input_structure} #include "${STRUCTURE}.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -508,7 +514,9 @@ const ${STRUCTURE} some_${STRUCTURE}; type_info const & typeid_${STRUCTURE}=typeid(some_${STRUCTURE}); const unsigned tinfo_${STRUCTURE}=structure::register_new("${STRUCTURE}"); +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE END_OF_IMPLEMENTATION diff --git a/ginac/symbol.cpp b/ginac/symbol.cpp index f1dc18df..1bea2cec 100644 --- a/ginac/symbol.cpp +++ b/ginac/symbol.cpp @@ -29,7 +29,9 @@ #include "idx.h" #include "debugmsg.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE ////////// // default constructor, destructor, copy constructor assignment operator and helpers @@ -281,4 +283,6 @@ symbol::assigned_ex_info::assigned_ex_info(void) : is_assigned(0), refcount(1) { } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/symbol.h b/ginac/symbol.h index 9905f3c8..d315efc5 100644 --- a/ginac/symbol.h +++ b/ginac/symbol.h @@ -27,7 +27,9 @@ #include #include +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** Basic CAS symbol. It has a name because it must know how to output itself. * It may be assigned an expression, but this feature is only intended for @@ -127,6 +129,8 @@ inline int degree(symbol const & a, symbol const & s) inline int ldegree(symbol const & a, symbol const & s) { return a.ldegree(s); } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_SYMBOL_H__ diff --git a/ginac/tinfos.h b/ginac/tinfos.h index 2c807b12..d13e2b95 100644 --- a/ginac/tinfos.h +++ b/ginac/tinfos.h @@ -23,7 +23,9 @@ #ifndef __GINAC_TINFOS_H__ #define __GINAC_TINFOS_H__ +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE const unsigned TINFO_basic = 0x00000001U; @@ -67,6 +69,8 @@ const unsigned TINFO_idx = 0x000d0001U; const unsigned TINFO_coloridx = 0x000d1001U; const unsigned TINFO_lorentzidx = 0x000d1002U; +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_TINFOS_H__ diff --git a/ginac/utils.cpp b/ginac/utils.cpp index 0c99ad59..7592e403 100644 --- a/ginac/utils.cpp +++ b/ginac/utils.cpp @@ -22,7 +22,9 @@ #include "utils.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE /** Integer binary logarithm */ unsigned log2(unsigned n) @@ -119,4 +121,6 @@ int compare_pointers(void const * a, void const * b) // private // none +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE diff --git a/ginac/utils.h b/ginac/utils.h index 3c33162e..18a5e7bd 100644 --- a/ginac/utils.h +++ b/ginac/utils.h @@ -28,7 +28,9 @@ #include "config.h" #include "assertion.h" +#ifndef NO_GINAC_NAMESPACE namespace GiNaC { +#endif // ndef NO_GINAC_NAMESPACE template string ToString(T const & t) @@ -131,6 +133,8 @@ OutputIterator mymerge3(InputIterator1 first1, InputIterator1 last1, } } +#ifndef NO_GINAC_NAMESPACE } // namespace GiNaC +#endif // ndef NO_GINAC_NAMESPACE #endif // ndef __GINAC_UTILS_H__ diff --git a/ginsh/ginsh.h b/ginsh/ginsh.h index c225fb09..2d32f0e7 100644 --- a/ginsh/ginsh.h +++ b/ginsh/ginsh.h @@ -42,7 +42,10 @@ extern "C" { #endif #include + +#ifndef NO_GINAC_NAMESPACE using namespace GiNaC; +#endif // ndef NO_GINAC_NAMESPACE // yacc stack type #define YYSTYPE ex diff --git a/ginsh/ginsh_parser.yy b/ginsh/ginsh_parser.yy index f8702d2a..b8409ea0 100644 --- a/ginsh/ginsh_parser.yy +++ b/ginsh/ginsh_parser.yy @@ -554,7 +554,10 @@ static ex f_ginac_function(const exprseq &es, int serial) } // All registered GiNaC functions -void GiNaC::ginsh_get_ginac_functions(void) +#ifndef NO_GINAC_NAMESPACE +#else // ndef NO_GINAC_NAMESPACE +void ginsh_get_ginac_functions(void) +#endif // ndef NO_GINAC_NAMESPACE { vector::const_iterator i = function::registered_functions().begin(), end = function::registered_functions().end(); unsigned serial = 0; -- 2.44.0 From 78c44ad5dc4b1c70c06bf57c117fb0da94b1dbd3 Mon Sep 17 00:00:00 2001 From: Alexander Frink Date: Thu, 2 Dec 1999 18:49:37 +0000 Subject: [PATCH 14/16] function.pl did not compile --- ginac/function.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ginac/function.pl b/ginac/function.pl index 6493042b..41018c93 100755 --- a/ginac/function.pl +++ b/ginac/function.pl @@ -183,11 +183,11 @@ $declare_function_macro_no_namespace #ifndef NO_GINAC_NAMESPACE #define REGISTER_FUNCTION(NAME,E,EF,D,S) \\ - const unsigned function_index_##NAME=GiNaC::function::register_new(#NAME,E,EF,D,S); #else // ndef NO_GINAC_NAMESPACE +#define REGISTER_FUNCTION(NAME,E,EF,D,S) \\ const unsigned function_index_##NAME=function::register_new(#NAME,E,EF,D,S); #endif // ndef NO_GINAC_NAMESPACE -- 2.44.0 From 181a5ff25eee13bdb9066d48143a3d321288e4b3 Mon Sep 17 00:00:00 2001 From: Alexander Frink Date: Thu, 2 Dec 1999 18:55:08 +0000 Subject: [PATCH 15/16] ginsh did not compile --- ginsh/ginsh_parser.yy | 1 + 1 file changed, 1 insertion(+) diff --git a/ginsh/ginsh_parser.yy b/ginsh/ginsh_parser.yy index b8409ea0..c49e7c0d 100644 --- a/ginsh/ginsh_parser.yy +++ b/ginsh/ginsh_parser.yy @@ -555,6 +555,7 @@ static ex f_ginac_function(const exprseq &es, int serial) // All registered GiNaC functions #ifndef NO_GINAC_NAMESPACE +void GiNaC::ginsh_get_ginac_functions(void) #else // ndef NO_GINAC_NAMESPACE void ginsh_get_ginac_functions(void) #endif // ndef NO_GINAC_NAMESPACE -- 2.44.0 From c76a85d9ad2a9beeac6e26cb5c24a1bdbca911ed Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Thu, 2 Dec 1999 22:28:00 +0000 Subject: [PATCH 16/16] - added the beta function to GiNaC - threw out ginsh's beta function - added a check for first polygamma function --- check/inifcns_consist.cpp | 26 ++++++++++++- ginac/inifcns.h | 4 ++ ginac/inifcns_gamma.cpp | 77 +++++++++++++++++++++++++++++++++++++-- ginsh/ginsh.1 | 3 -- ginsh/ginsh_parser.yy | 4 +- 5 files changed, 104 insertions(+), 10 deletions(-) diff --git a/check/inifcns_consist.cpp b/check/inifcns_consist.cpp index 024dad79..25e34197 100644 --- a/check/inifcns_consist.cpp +++ b/check/inifcns_consist.cpp @@ -169,8 +169,8 @@ static unsigned inifcns_consist_trans(void) return result; } -/* Simple tests on the Gamma combinatorial function. We stuff in arguments - * where the result exists in closed form and check if it's ok. */ +/* Simple tests on the Gamma function. We stuff in arguments where the results + * exists in closed form and check if it's ok. */ static unsigned inifcns_consist_gamma(void) { unsigned result = 0; @@ -214,6 +214,27 @@ static unsigned inifcns_consist_gamma(void) return result; } +/* Simple tests on the Psi-function (aka polygamma-function). We stuff in + arguments where the result exists in closed form and check if it's ok. */ +static unsigned inifcns_consist_psi(void) +{ + unsigned result = 0; + symbol x; + ex e; + + // We check psi(1) and psi(1/2) implicitly by calculating the curious + // little identity gamma(1)'/gamma(1) - gamma(1/2)'/gamma(1/2) == 2*log(2). + e += (gamma(x).diff(x)/gamma(x)).subs(x==numeric(1)); + e -= (gamma(x).diff(x)/gamma(x)).subs(x==numeric(1,2)); + if (e!=2*log(2)) { + clog << "gamma(1)'/gamma(1) - gamma(1/2)'/gamma(1/2) erroneously returned " + << e << " instead of 2*log(2)" << endl; + ++result; + } + + return result; +} + /* Simple tests on the Riemann Zeta function. We stuff in arguments where the * result exists in closed form and check if it's ok. Of course, this checks * the Bernoulli numbers as a side effect. */ @@ -253,6 +274,7 @@ unsigned inifcns_consist(void) result += inifcns_consist_cos(); result += inifcns_consist_trans(); result += inifcns_consist_gamma(); + result += inifcns_consist_psi(); result += inifcns_consist_zeta(); if ( !result ) { diff --git a/ginac/inifcns.h b/ginac/inifcns.h index 84e0dbcb..a5a52700 100644 --- a/ginac/inifcns.h +++ b/ginac/inifcns.h @@ -88,7 +88,11 @@ DECLARE_FUNCTION_1P(zeta) /** Gamma-function. */ DECLARE_FUNCTION_1P(gamma) +/** Beta-function. */ +DECLARE_FUNCTION_2P(beta) + /** Psi-function (aka polygamma-function). */ +// overloading @ work: we cannot use the macros extern const unsigned function_index_psi1; inline function psi(ex const & p1) { return function(function_index_psi1, p1); diff --git a/ginac/inifcns_gamma.cpp b/ginac/inifcns_gamma.cpp index 2fd58cce..0d59eb30 100644 --- a/ginac/inifcns_gamma.cpp +++ b/ginac/inifcns_gamma.cpp @@ -1,7 +1,7 @@ /** @file inifcns_gamma.cpp * - * Implementation of Gamma-function, Polygamma-functions, and some related - * stuff. */ + * Implementation of Gamma-function, Beta-function, Polygamma-functions, and + * some related stuff. */ /* * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany @@ -53,7 +53,7 @@ static ex gamma_eval(ex const & x) if (x.info(info_flags::posint)) { return factorial(ex_to_numeric(x).sub(numONE())); } else { - return numZERO(); // Infinity. Throw? What? + throw (std::domain_error("gamma_eval(): simple pole")); } } // trap half integer arguments: @@ -106,6 +106,77 @@ static ex gamma_series(ex const & x, symbol const & s, ex const & point, int ord REGISTER_FUNCTION(gamma, gamma_eval, gamma_evalf, gamma_diff, gamma_series); +////////// +// Beta-function +////////// + +static ex beta_eval(ex const & x, ex const & y) +{ + if (x.info(info_flags::numeric) && y.info(info_flags::numeric)) { + numeric nx(ex_to_numeric(x)); + numeric ny(ex_to_numeric(y)); + // treat all problematic x and y that may not be passed into gamma, + // because they would throw there although beta(x,y) is well-defined: + if (nx.is_real() && nx.is_integer() && + ny.is_real() && ny.is_integer()) { + if (nx.is_negative()) { + if (nx<=-ny) + return numMINUSONE().power(ny)*beta(1-x-y, y); + else + throw (std::domain_error("beta_eval(): simple pole")); + } + if (ny.is_negative()) { + if (ny<=-nx) + return numMINUSONE().power(nx)*beta(1-y-x, x); + else + throw (std::domain_error("beta_eval(): simple pole")); + } + return gamma(x)*gamma(y)/gamma(x+y); + } + // no problem in numerator, but denominator has pole: + if ((nx+ny).is_real() && + (nx+ny).is_integer() && + !(nx+ny).is_positive()) + return exZERO(); + return gamma(x)*gamma(y)/gamma(x+y); + } + return beta(x,y).hold(); +} + +static ex beta_evalf(ex const & x, ex const & y) +{ + BEGIN_TYPECHECK + TYPECHECK(x,numeric) + TYPECHECK(y,numeric) + END_TYPECHECK(beta(x,y)) + + return gamma(ex_to_numeric(x))*gamma(ex_to_numeric(y)) + / gamma(ex_to_numeric(x+y)); +} + +static ex beta_diff(ex const & x, ex const & y, unsigned diff_param) +{ + GINAC_ASSERT(diff_param<2); + ex retval; + + if (diff_param==0) // d/dx beta(x,y) + retval = (psi(x)-psi(x+y))*beta(x,y); + if (diff_param==1) // d/dy beta(x,y) + retval = (psi(y)-psi(x+y))*beta(x,y); + return retval; +} + +static ex beta_series(ex const & x, ex const & y, symbol const & s, ex const & point, int order) +{ + if (x.is_equal(s) && point.is_zero()) { + ex e = 1 / s - EulerGamma + s * (pow(Pi, 2) / 12 + pow(EulerGamma, 2) / 2) + Order(pow(s, 2)); + return e.series(s, point, order); + } else + throw(std::logic_error("don't know the series expansion of this particular beta function")); +} + +REGISTER_FUNCTION(beta, beta_eval, beta_evalf, beta_diff, beta_series); + ////////// // Psi-function (aka polygamma-function) ////////// diff --git a/ginsh/ginsh.1 b/ginsh/ginsh.1 index 32b0cec6..cf3b945c 100644 --- a/ginsh/ginsh.1 +++ b/ginsh/ginsh.1 @@ -216,9 +216,6 @@ detail here. Please refer to the GiNaC documentation. .PP .RS \" GINSH_FCN_HELP_START -.BI beta( expression ", " expression ) -\- beta function -.br .BI charpoly( matrix ", " symbol ) \- characteristic polynomial of a matrix .br diff --git a/ginsh/ginsh_parser.yy b/ginsh/ginsh_parser.yy index c49e7c0d..2e02b6cc 100644 --- a/ginsh/ginsh_parser.yy +++ b/ginsh/ginsh_parser.yy @@ -242,7 +242,6 @@ static void push(const ex &e) * Built-in functions */ -static ex f_beta(const exprseq &e) {return gamma(e[0])*gamma(e[1])/gamma(e[0]+e[1]);} static ex f_denom(const exprseq &e) {return e[0].denom();} static ex f_eval1(const exprseq &e) {return e[0].eval();} static ex f_evalf1(const exprseq &e) {return e[0].evalf();} @@ -483,7 +482,6 @@ struct fcn_init { }; static const fcn_init builtin_fcns[] = { - {"beta", fcn_desc(f_beta, 2)}, {"charpoly", fcn_desc(f_charpoly, 2)}, {"coeff", fcn_desc(f_coeff, 3)}, {"collect", fcn_desc(f_collect, 2)}, @@ -759,8 +757,10 @@ int main(int argc, char **argv) insert_fcn_help("atan", "inverse tangent function"); insert_fcn_help("atan2", "inverse tangent function with two arguments"); insert_fcn_help("atanh", "inverse hyperbolic tangent function"); + insert_fcn_help("beta", "beta function"); insert_fcn_help("cos", "cosine function"); insert_fcn_help("cosh", "hyperbolic cosine function"); + insert_fcn_help("psi", "polygamma function"); insert_fcn_help("sin", "sine function"); insert_fcn_help("sinh", "hyperbolic sine function"); insert_fcn_help("tan", "tangent function"); -- 2.44.0