]> www.ginac.de Git - ginac.git/commitdiff
Initial revision
authorRichard Kreckel <Richard.Kreckel@uni-mainz.de>
Mon, 8 Nov 1999 21:43:49 +0000 (21:43 +0000)
committerRichard Kreckel <Richard.Kreckel@uni-mainz.de>
Mon, 8 Nov 1999 21:43:49 +0000 (21:43 +0000)
39 files changed:
COPYING [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.in [new file with mode: 0644]
aclocal.m4 [new file with mode: 0644]
check/Makefile.in [new file with mode: 0644]
check/check.h [new file with mode: 0644]
check/differentiation.cpp [new file with mode: 0644]
check/expand_subs.cpp [new file with mode: 0644]
check/fcntimer.cpp [new file with mode: 0644]
check/inifcns_consist.cpp [new file with mode: 0644]
check/lsolve_onedim.cpp [new file with mode: 0644]
check/main.cpp [new file with mode: 0644]
check/matrix_checks.cpp [new file with mode: 0644]
check/normalization.cpp [new file with mode: 0644]
check/numeric_consist.cpp [new file with mode: 0644]
check/numeric_output.cpp [new file with mode: 0644]
check/paranoia_check.cpp [new file with mode: 0644]
check/poly_gcd.cpp [new file with mode: 0644]
check/powerlaws.cpp [new file with mode: 0644]
check/result.ref [new file with mode: 0644]
check/series_expansion.cpp [new file with mode: 0644]
config.h.in [new file with mode: 0644]
configure [new file with mode: 0755]
configure.in [new file with mode: 0644]
doc/DoxyfileHTML [new file with mode: 0644]
doc/DoxyfileTEX [new file with mode: 0644]
doc/Doxyfooter.html [new file with mode: 0644]
doc/Makefile [new file with mode: 0644]
doc/Makefile.in [new file with mode: 0644]
doc/classhierarchy.fig [new file with mode: 0644]
doc/powerlaws.tex [new file with mode: 0644]
doc/rep_naive.fig [new file with mode: 0644]
doc/rep_pair.fig [new file with mode: 0644]
doc/tutorial.sgml.in [new file with mode: 0644]
ginsh/Makefile.in [new file with mode: 0644]
ginsh/ginsh.1 [new file with mode: 0644]
ginsh/ginsh.h [new file with mode: 0644]
ginsh/ginsh.l [new file with mode: 0644]
ginsh/ginsh.y [new file with mode: 0644]

diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..12065f3
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          59 Temple Place - Suite 330, Boston, MA
+                          02111-1307, USA.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+\f
+        Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..750d516
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,27 @@
+Installation:
+=============
+
+As with any autoconfiguring GNU software, installation is as easy as this:
+
+sysprompt> ./configure
+sysprompt> make
+sysprompt> make check
+sysprompt> make install
+
+Known to work with:
+  - Linux/x86, EGCS-1.1.2 or GCC 2-95.
+
+The "make" step takes about 10 minutes, on a 586 DX / 133 MHz / 64 MB or
+about 2 minutes on a P-III /550 MHz / 512 MB.
+
+More detailed installation instructions can be found in the documentation,
+in the doc/ directory.
+
+
+Problems with CLN:
+==================
+
+You should use at least CLN V1.0.2, since all earlier ones are
+somewhat buggy.  Even V1.0.1 has a few problems and GiNaC will not
+support older versions.  Please install it properly on your system
+before continuing with GiNaC.
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..8eae851
--- /dev/null
@@ -0,0 +1,115 @@
+# This is the prototype Makefile for the GiNaC package. 
+
+# Not every make knows what CXX is, so we inherit it together with some other
+# values from configure which checks it anyways:
+CXX = @CXX@
+CXXFLAGS = @CXXFLAGS@
+CPPFLAGS = @CPPFLAGS@
+DEFS = @DEFS@
+LIBS = @LIBS@
+LDFLAGS = @LDFLAGS@
+
+# Here come the usual install directories in GNU-configure fashion:
+srcdir = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+libdir = @libdir@
+includedir = @includedir@/GiNaC
+
+# This must be empty unless the user has called configure with --enable-shared:
+shared = @shared@
+
+# The version-number is tracked in configure.in only:
+LIBGINACVER = @LibGiNaC_Ver@
+
+# Autoconf macro AC_PROC_INSTALL sets these:
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+
+all:   lib ginsh
+       echo "now type make install"
+
+src/libginac.la:
+       cd src; ${MAKE} libginac.la
+
+src/.libs/libginac.a:
+       cd src; ${MAKE} .libs/libginac.a
+
+lib:
+       cd src; ${MAKE} all
+
+# Target for running a test-suite across the library:
+check:
+       if [ "${shared}" ]; then \
+               ${MAKE} sharedcheck; \
+       else \
+               ${MAKE} staticcheck; \
+       fi
+
+sharedcheck: src/libginac.la
+       cd check; ${MAKE} sharedcheck
+
+staticcheck: src/.libs/libginac.a
+       cd check; ${MAKE} staticcheck
+
+# Target for making the Ginac INteractive SHell ginsh:
+ginsh:
+       cd ginsh; ${MAKE} all
+
+# Targets for installation in install directories.  The user-visible target
+# `install' determines which one to call (static lib only or both shared and
+# static lib).
+install: 
+       @ if [ "${shared}" ]; then \
+               ${MAKE} shlibinst; \
+       else \
+               ${MAKE} libinst; \
+       fi
+       ${INSTALL} -d ${includedir}
+       ${INSTALL_DATA} include/* ${includedir}/
+       cd ginsh; ${MAKE} install
+       cd doc; ${MAKE} install
+
+shlibinst: libginac.la
+       ${INSTALL} -d ${libdir}
+       ${LIBTOOL} install libginac.la ${libdir}/libginac.la
+       ${LIBTOOL} -n --finish ${libdir}
+
+libinst: .libs/libginac.a
+       ${INSTALL} -d ${libdir}
+       ${INSTALL_DATA} .libs/libginac.a ${libdir}/libginac.a
+
+# Targets for cleaning up. (clean deletes files created by built, distclean
+# deletes files created by configuration, uninstall removes all files related
+# to GiNaC from the system.)
+clean:
+       cd src; ${MAKE} clean
+       cd check; ${MAKE} clean
+       cd ginsh; ${MAKE} clean
+
+distclean: clean
+       cd src; ${MAKE} distclean
+       cd check; ${MAKE} distclean
+       cd ginsh; ${MAKE} distclean
+       rm -f config.status config.log config.cache config.h Makefile
+
+uninstall:
+       rm -f ${libdir}/libginac.*
+       rm -rf ${includedir}
+       cd ginsh; ${MAKE} uninstall
+       cd doc; ${MAKE} uninstall
+
+# Convenient targets for those who wish to extend on the documentation:
+doc:
+       cd doc; ${MAKE} all
+reference:
+       cd doc; ${MAKE} reference
+tutorial:
+       cd doc; ${MAKE} tutorial
+
+# Special dummy targets:
+.PHONY: clean distclean all install uninstall check ginsh doc
+.SUFFIXES: .o .lo .cpp
+.SILENT: all check sharedcheck staticcheck doc reference tutorial
+
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644 (file)
index 0000000..fff1839
--- /dev/null
@@ -0,0 +1,116 @@
+dnl ===========================================================================
+dnl Additional macros used to configure GiNaC.  We don't start additions' names
+dnl with AC_ but with GINAC_ in order to avoid future trouble.
+dnl ===========================================================================
+
+dnl Generally, it is a bad idea to put specialized header files for a library
+dnl into a generic directory like /usr/local/include/.  Instead, one should put
+dnl them into a subdirectory.  GiNaC does it, NTL does it.  Unfortunately, CLN
+dnl doesn't do so but some people choose to do it by hand.  In these cases we
+dnl need to #include <CLN/cln.h>, otherwise #include <cln.h>.  This macro
+dnl tries to be clever and find out the correct way by defining the variable
+dnl HAVE_CLN_CLN_H in config.h:
+AC_DEFUN(GINAC_CHECK_CLN_H,
+    [AC_PROVIDE([$0])
+    AC_CHECK_HEADERS(CLN/cln.h, ,
+        AC_CHECK_HEADERS(cln.h, ,
+            AC_MSG_ERROR([cannot find header for Bruno Haible's CLN]);
+        )
+    )
+])
+
+dnl This macro is needed because the generic AC_CHECK_LIB doesn't work because
+dnl C++ is more strongly typed than C.  Therefore we need to work with the 
+dnl more fundamental AC_TRY_LINK instead.
+AC_DEFUN(GINAC_CHECK_LIBCLN,
+    [AC_PROVIDE([$0])
+    AC_MSG_CHECKING([how to link with libcln])
+    saved_LIBS="${LIBS}"
+    AC_CACHE_VAL(ginac_cv_lib_cln_link,
+        [LIBS="-lcln"
+        case "${ac_cv_header_CLN_cln_h}" in
+        "yes")
+            AC_TRY_LINK([#include <CLN/cln.h>],
+                [factorial(1);],
+                ginac_cv_lib_cln_link="-lcln",
+                ginac_cv_lib_cln_link="fail")
+            ;;
+        *)
+            AC_TRY_LINK([#include <cln.h>],
+                [factorial(1);],
+                ginac_cv_lib_cln_link="-lcln",
+                ginac_cv_lib_cln_link="fail")
+            ;;
+        esac
+    ])
+    case "${ginac_cv_lib_cln_link}" in
+dnl linking worked:
+    "-lcln")
+        LIBS="-lcln ${saved_LIBS}"
+        AC_MSG_RESULT([-lcln])
+        GINAC_CHECK_LIBCLN_SANITY
+    ;;
+dnl linking failed:
+    "fail")
+        LIBS="${saved_LIBS}"
+        AC_MSG_RESULT([])
+        AC_MSG_WARN([linking with libcln failed])
+    ;;
+dnl should never ever get here:
+    *)
+        LIBS="${saved_LIBS}"
+    ;;
+    esac
+])
+
+dnl Check if the CLN library suits our needs, i.e. if it is new enough, by
+dnl trying to run into a little bug which was present till version 1.0.1 and
+dnl then removed.
+AC_DEFUN(GINAC_CHECK_LIBCLN_SANITY,
+    [AC_PROVIDE([$0])
+    AC_MSG_CHECKING([whether libcln behaves sane])
+    AC_CACHE_VAL(ginac_cv_lib_cln_integrity,
+        [
+        case "${ac_cv_header_CLN_cln_h}" in
+        "yes")
+            AC_TRY_RUN([#include <CLN/cln.h>
+int main() {
+cl_RA q(3); q = q/2; cl_RA p(3); p = p/2;
+if (q+p != 3) return 1; else return 0;
+}],
+                ginac_cv_lib_cln_integrity="sane",
+                ginac_cv_lib_cln_integrity="insane",
+                ginac_cv_lib_cln_integrity="guessing sane")
+            ;;
+        *)
+            AC_TRY_RUN([#include <cln.h>
+int main() {
+cl_RA q(3); q = q/2; cl_RA p(3); p = p/2;
+if (q+p != 3) return 1; else return 0;
+}],
+                ginac_cv_lib_cln_integrity="sane",
+                ginac_cv_lib_cln_integrity="insane",
+                ginac_cv_lib_cln_integrity="guessing sane")
+            ;;
+        esac
+    ])
+    case "${ginac_cv_lib_cln_integrity}" in
+dnl exit status was 0:
+    "sane")
+        AC_MSG_RESULT([yes])
+    ;;
+dnl exit status was not 0:
+    "insane")
+        AC_MSG_RESULT([no])
+        AC_MSG_WARN([maybe version of libcln is older than 1.0.2?])
+    ;;
+dnl test-program was not run because we are cross-compiling:
+    "guessing sane")
+        AC_MSG_RESULT([hopefully])
+    ;;
+dnl should never ever get here:
+    *)
+        AC_MSG_WARN([you found a bug in the configure script!])
+    ;;
+    esac
+])
diff --git a/check/Makefile.in b/check/Makefile.in
new file mode 100644 (file)
index 0000000..6572b14
--- /dev/null
@@ -0,0 +1,58 @@
+# This is the Makefile for GiNaC's consistency checks.
+
+# Not every make knows what CXX is, so we inherit it together with some other
+# values from configure which checks it anyways:
+CXX = @CXX@
+CXXFLAGS = @CXXFLAGS@
+CPPFLAGS = @CPPFLAGS@ -I../include
+DEFS = @DEFS@
+LIBS = @LIBS@
+LDFLAGS = @LDFLAGS@
+
+# Here come the usual install directories in GNU-configure fashion:
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+libdir = @libdir@
+includedir = @includedir@
+
+# This must be empty unless the user has called configure with --enable-shared:
+shared = @shared@
+
+OBJECTS = paranoia_check.o numeric_output.o numeric_consist.o powerlaws.o \
+          expand_subs.o inifcns_consist.o differentiation.o poly_gcd.o \
+          normalization.o lsolve_onedim.o matrix_checks.o series_expansion.o \
+          fcntimer.o main.o
+
+all: 
+       echo "Please call it with 'make check' from top-level Makefile."
+       echo "Alternatively, you can use this Makefile's targets {shared|static}check"
+       echo "depending on your personal preferences and which lib you built."
+
+sharedcheck: ${OBJECTS} ../src/.libs/libginac.so
+       ${CXX} ${LDFLAGS} ${OBJECTS} -Wl,--rpath -Wl,../src/.libs -L../src/.libs -lginac ${LIBS} -o main
+       @echo -n "Running "
+       ./main 2> result.out
+       @echo -n "comparing output: "
+       cmp result.ref result.out
+
+staticcheck: ${OBJECTS} ../src/.libs/libginac.a
+       ${CXX} ${LDFLAGS} ${OBJECTS} ../src/.libs/libginac.a ${LIBS} -o main
+       @echo -n "Running "
+       ./main 2> result.out
+       @echo -n "comparing output: "
+       cmp result.ref result.out
+
+# Special dummy targets:
+.PHONY: clean distclean all sharedcheck staticcheck
+.SUFFIXES: .o .cpp
+.SILENT: all
+
+clean:
+       rm -f *.o main core result.out
+
+distclean: clean
+       rm -f Makefile
+
+# Suffix rules:
+.cpp.o :
+       ${CXX} ${CPPFLAGS} ${CXXFLAGS} ${DEFS} -c $<
diff --git a/check/check.h b/check/check.h
new file mode 100644 (file)
index 0000000..68622d9
--- /dev/null
@@ -0,0 +1,24 @@
+// check/check.h
+
+#ifndef _CHECK_H_
+#define _CHECK_H_
+
+// fcntimer is defined in timer.cpp and used for timing check functions only:
+unsigned fcntimer(unsigned fcn());
+
+// prototypes for all individual checks must be unsigned fcn() in order to be
+// able to use fcntimer() as a wrapper:
+unsigned paranoia_check();
+unsigned numeric_output();
+unsigned numeric_consist();
+unsigned powerlaws();
+unsigned expand_subs();
+unsigned inifcns_consist();
+unsigned differentiation();
+unsigned poly_gcd();
+unsigned normalization();
+unsigned matrix_checks();
+unsigned lsolve_onedim();
+unsigned series_expansion();
+
+#endif // ndef _CHECK_H_
diff --git a/check/differentiation.cpp b/check/differentiation.cpp
new file mode 100644 (file)
index 0000000..e917bd7
--- /dev/null
@@ -0,0 +1,233 @@
+// check/differentiation.cpp
+
+/* Tests for symbolic differentiation, including various functions. */
+
+#include "ginac.h"
+
+static unsigned check_diff(const ex &e, const symbol &x,
+                           const ex &d, unsigned nth=1)
+{
+    ex ed = e.diff(x, nth);
+    if ((ed - d).compare(exZERO()) != 0) {
+        switch (nth) {
+        case 0:
+            clog << "zeroth ";
+            break;
+        case 1:
+            break;
+        case 2:
+            clog << "second ";
+            break;
+        case 3:
+            clog << "third ";
+            break;
+        default:
+            clog << nth << "th ";
+        }
+        clog << "derivative of " << e << " by " << x << " returned "
+             << ed << " instead of " << d << endl;
+        clog << "returned:" << endl;
+        ed.printtree(clog);
+        clog << endl << "instead of" << endl;
+        d.printtree(clog);
+
+        return 1;
+    }
+    return 0;
+}
+
+// Simple (expanded) polynomials
+static unsigned differentiation1(void)
+{
+    unsigned result = 0;
+    symbol x("x"), y("y");
+    ex e1, e2, e, d;
+    
+    // construct bivariate polynomial e to be diff'ed:
+    e1 = pow(x, -2) * 3 + pow(x, -1) * 5 + 7 + x * 11 + pow(x, 2) * 13;
+    e2 = pow(y, -2) * 5 + pow(y, -1) * 7 + 11 + y * 13 + pow(y, 2) * 17;
+    e = (e1 * e2).expand();
+    
+    // d e / dx:
+    d = 121 - 55*pow(x,-2) - 66*pow(x,-3) - 30*pow(x,-3)*pow(y,-2)
+        - 42*pow(x,-3)*pow(y,-1) - 78*pow(x,-3)*y
+        - 102*pow(x,-3)*pow(y,2) - 25*pow(x,-2) * pow(y,-2)
+        - 35*pow(x,-2)*pow(y,-1) - 65*pow(x,-2)*y
+        - 85*pow(x,-2)*pow(y,2) + 77*pow(y,-1) + 143*y + 187*pow(y,2)
+        + 130*x*pow(y,-2) + 182*pow(y,-1)*x + 338*x*y + 442*x*pow(y,2)
+        + 55*pow(y,-2) + 286*x;
+    result += check_diff(e, x, d);
+    
+    // d e / dy:
+    d = 91 - 30*pow(x,-2)*pow(y,-3) - 21*pow(x,-2)*pow(y,-2)
+        + 39*pow(x,-2) + 102*pow(x,-2)*y - 50*pow(x,-1)*pow(y,-3)
+        - 35*pow(x,-1)*pow(y,-2) + 65*pow(x,-1) + 170*pow(x,-1)*y
+        - 77*pow(y,-2)*x + 143*x + 374*x*y - 130*pow(y,-3)*pow(x,2)
+        - 91*pow(y,-2)*pow(x,2) + 169*pow(x,2) + 442*pow(x,2)*y
+        - 110*pow(y,-3)*x - 70*pow(y,-3) + 238*y - 49*pow(y,-2);
+    result += check_diff(e, y, d);
+    
+    // d^2 e / dx^2:
+    d = 286 + 90*pow(x,-4)*pow(y,-2) + 126*pow(x,-4)*pow(y,-1)
+        + 234*pow(x,-4)*y + 306*pow(x,-4)*pow(y,2)
+        + 50*pow(x,-3)*pow(y,-2) + 70*pow(x,-3)*pow(y,-1)
+        + 130*pow(x,-3)*y + 170*pow(x,-3)*pow(y,2)
+        + 130*pow(y,-2) + 182*pow(y,-1) + 338*y + 442*pow(y,2)
+        + 198*pow(x,-4) + 110*pow(x,-3);
+    result += check_diff(e, x, d, 2);
+    
+    // d^2 e / dy^2:
+    d = 238 + 90*pow(x,-2)*pow(y,-4) + 42*pow(x,-2)*pow(y,-3)
+        + 102*pow(x,-2) + 150*pow(x,-1)*pow(y,-4)
+        + 70*pow(x,-1)*pow(y,-3) + 170*pow(x,-1) + 330*x*pow(y,-4)
+        + 154*x*pow(y,-3) + 374*x + 390*pow(x,2)*pow(y,-4)
+        + 182*pow(x,2)*pow(y,-3) + 442*pow(x,2) + 210*pow(y,-4)
+        + 98*pow(y,-3);
+    result += check_diff(e, y, d, 2);
+    
+    return result;
+}
+
+// Trigonometric and transcendental functions
+static unsigned differentiation2(void)
+{
+    unsigned result = 0;
+    symbol x("x"), y("y"), a("a"), b("b");
+    ex e1, e2, e, d;
+    
+    // construct expression e to be diff'ed:
+    e1 = y*pow(x, 2) + a*x + b;
+    e2 = sin(e1);
+    e = b*pow(e2, 2) + y*e2 + a;
+    
+    d = 2*b*e2*cos(e1)*(2*x*y + a) + y*cos(e1)*(2*x*y + a);
+    result += check_diff(e, x, d);
+    
+    d = 2*b*pow(cos(e1),2)*pow(2*x*y + a, 2) + 4*b*y*e2*cos(e1)
+        - 2*b*pow(e2,2)*pow(2*x*y + a, 2) - y*e2*pow(2*x*y + a, 2)
+        + 2*pow(y,2)*cos(e1);
+    result += check_diff(e, x, d, 2);
+    
+    d = 2*b*e2*cos(e1)*pow(x, 2) + e2 + y*cos(e1)*pow(x, 2);
+    result += check_diff(e, y, d);
+
+    d = 2*b*pow(cos(e1),2)*pow(x,4) - 2*b*pow(e2,2)*pow(x,4)
+        + 2*cos(e1)*pow(x,2) - y*e2*pow(x,4);
+    result += check_diff(e, y, d, 2);
+    
+    // construct expression e to be diff'ed:
+    e2 = cos(e1);
+    e = b*pow(e2, 2) + y*e2 + a;
+    
+    d = -2*b*e2*sin(e1)*(2*x*y + a) - y*sin(e1)*(2*x*y + a);
+    result += check_diff(e, x, d);
+    
+    d = 2*b*pow(sin(e1),2)*pow(2*y*x + a,2) - 4*b*e2*sin(e1)*y 
+        - 2*b*pow(e2,2)*pow(2*y*x + a,2) - y*e2*pow(2*y*x + a,2)
+        - 2*pow(y,2)*sin(e1);
+    result += check_diff(e, x, d, 2);
+    
+    d = -2*b*e2*sin(e1)*pow(x,2) + e2 - y*sin(e1)*pow(x, 2);
+    result += check_diff(e, y, d);
+    
+    d = -2*b*pow(e2,2)*pow(x,4) + 2*b*pow(sin(e1),2)*pow(x,4)
+        - 2*sin(e1)*pow(x,2) - y*e2*pow(x,4);
+    result += check_diff(e, y, d, 2);
+    
+    // construct expression e to be diff'ed:
+    e2 = exp(e1);
+    e = b*pow(e2, 2) + y*e2 + a;
+    
+    d = 2*b*pow(e2, 2)*(2*x*y + a) + y*e2*(2*x*y + a);
+    result += check_diff(e, x, d);
+    
+    d = 4*b*pow(e2,2)*pow(2*y*x + a,2) + 4*b*pow(e2,2)*y
+        + 2*pow(y,2)*e2 + y*e2*pow(2*y*x + a,2);
+    result += check_diff(e, x, d, 2);
+    
+    d = 2*b*pow(e2,2)*pow(x,2) + e2 + y*e2*pow(x,2);
+    result += check_diff(e, y, d);
+    
+    d = 4*b*pow(e2,2)*pow(x,4) + 2*e2*pow(x,2) + y*e2*pow(x,4);
+    result += check_diff(e, y, d, 2);
+    
+    // construct expression e to be diff'ed:
+    e2 = log(e1);
+    e = b*pow(e2, 2) + y*e2 + a;
+    
+    d = 2*b*e2*(2*x*y + a)/e1 + y*(2*x*y + a)/e1;
+    result += check_diff(e, x, d);
+    
+    d = 2*b*pow((2*x*y + a),2)*pow(e1,-2) + 4*b*y*e2/e1
+        - 2*b*e2*pow(2*x*y + a,2)*pow(e1,-2) + 2*pow(y,2)/e1
+        - y*pow(2*x*y + a,2)*pow(e1,-2);
+    result += check_diff(e, x, d, 2);
+    
+    d = 2*b*e2*pow(x,2)/e1 + e2 + y*pow(x,2)/e1;
+    result += check_diff(e, y, d);
+    
+    d = 2*b*pow(x,4)*pow(e1,-2) - 2*b*e2*pow(e1,-2)*pow(x,4)
+        + 2*pow(x,2)/e1 - y*pow(x,4)*pow(e1,-2);
+    result += check_diff(e, y, d, 2);
+    
+    // test for functions with two variables: atan2
+    e1 = y*pow(x, 2) + a*x + b;
+    e2 = x*pow(y, 2) + b*y + a;
+    e = atan2(e1,e2);
+    /*
+    d = pow(y,2)*(-b-y*pow(x,2)-a*x)/(pow(b+y*pow(x,2)+a*x,2)+pow(x*pow(y,2)+b*y+a,2))
+        +(2*y*x+a)/((x*pow(y,2)+b*y+a)*(1+pow(b*y*pow(x,2)+a*x,2)/pow(x*pow(y,2)+b*y+a,2)));
+    */
+    /*
+    d = ((a+2*y*x)*pow(y*b+pow(y,2)*x+a,-1)-(a*x+b+y*pow(x,2))*
+         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);
+    result += check_diff(e, x, d);
+    
+    return result;
+}
+
+// Series
+static unsigned differentiation3(void)
+{
+    symbol x("x");
+    ex e, d, ed;
+    
+    e = sin(x).series(x, exZERO(), 8);
+    d = cos(x).series(x, exZERO(), 7);
+    ed = e.diff(x);
+    ed = static_cast<series *>(ed.bp)->convert_to_poly();
+    d = static_cast<series *>(d.bp)->convert_to_poly();
+    
+    if ((ed - d).compare(exZERO()) != 0) {
+        clog << "derivative of " << e << " by " << x << " returned "
+             << ed << " instead of " << d << ")" << endl;
+        return 1;
+    }
+    return 0;
+}
+
+unsigned differentiation(void)
+{
+    unsigned result = 0;
+    
+    cout << "checking symbolic differentiation..." << flush;
+    clog << "---------symbolic differentiation:" << endl;
+    
+    result += differentiation1();
+    result += differentiation2();
+    result += differentiation3();
+    
+    if (!result) {
+        cout << " passed ";
+        clog << "(no output)" << endl;
+    } else {
+        cout << " failed ";
+    }
+    return result;
+}
diff --git a/check/expand_subs.cpp b/check/expand_subs.cpp
new file mode 100644 (file)
index 0000000..083eae5
--- /dev/null
@@ -0,0 +1,78 @@
+// check/expand_subs.cpp
+
+/* The first test routine implements Denny Fliegner's quick consistency check:
+ *     e = (a0 + a1 + a2 + a3 + ...)^2
+ *     expand e
+ *     substitute a0 by (-a2 - a3 - ...) in e
+ *     expand e
+ * after which e should be just a1^2.
+ * In addition, a simpler modification is tested in the second test:
+ *     e = (a0 + a1)^200
+ *     expand e
+ *     substitute a0 by -a1 in e
+ * after which e should return 0 (without expanding). */
+
+#include "ginac.h"
+
+#define VECSIZE 100
+
+static unsigned expand_subs1(void)
+{
+    symbol a1("a1");
+    symbol a[VECSIZE];
+    ex e, aux;
+
+    a[1] = a1;
+    for (unsigned i=0; i<VECSIZE; ++i) {
+        e = e + a[i];
+    }
+
+    // prepare aux so it will swallow anything but a1^2:
+    aux = -e + a[0] + a[1];
+    e = expand(subs(expand(pow(e, 2)), a[0] == aux));
+
+    if (e != pow(a1,2)) {
+        clog << "Denny Fliegner's quick consistency check erroneously returned "
+             << e << "." << endl;
+        return 1;
+    }
+    return 0;
+}
+
+static unsigned expand_subs2(void)
+{
+    symbol a("a"), b("b");
+    ex e, f;
+
+    // Here the final expand() should be superflous. For no particular reason
+    // at all, we don't use the wrapper-functions but the methods instead:
+    e = pow(a+b,200).expand();
+    f = e.subs(a == -b);
+
+    if (f != 0) {
+        clog << "e = pow(a+b,200).expand(); f = e.subs(a == -b); erroneously returned "
+             << f << " instead of simplifying to 0." << endl;
+        return 1;
+    }
+    return 0;
+}
+
+unsigned expand_subs(void)
+{
+    unsigned result = 0;
+
+    cout << "checking commutative expansion and substitution..." << flush;
+    clog << "---------commutative expansion and substitution:" << endl;
+
+    result += expand_subs1();
+    result += expand_subs2();
+
+    if (! result) {
+        cout << " passed ";
+        clog << "(no output)" << endl;
+    } else {
+        cout << " failed ";
+    }
+
+    return result;
+}
diff --git a/check/fcntimer.cpp b/check/fcntimer.cpp
new file mode 100644 (file)
index 0000000..897636d
--- /dev/null
@@ -0,0 +1,31 @@
+// check/fcntimer.cpp
+
+#include <stdio.h>
+#include <sys/resource.h>
+
+
+// fcntimer() is a little wrapper around GiNaC's automated checks.  All those
+// functions are passed void and return unsigned.  fcntimer() accepts one such
+// function fcn(), returns its result and as a side-effect prints to stdout how
+// much CPU time was consumed by fcn's execution in the fashion "(0.07s)\n".
+unsigned fcntimer(unsigned fcn())
+{
+    unsigned fcnresult;
+    struct rusage used1, used2;
+    double elapsed;
+
+    // time the execution of the function:
+    getrusage(RUSAGE_SELF, &used1);
+    fcnresult = fcn();
+    getrusage(RUSAGE_SELF, &used2);
+
+    // add elapsed user and system time in microseconds:
+    elapsed = ((used2.ru_utime.tv_sec - used1.ru_utime.tv_sec) +
+               (used2.ru_stime.tv_sec - used1.ru_stime.tv_sec) +
+               (used2.ru_utime.tv_usec - used1.ru_utime.tv_usec) / 1e6 +
+               (used2.ru_stime.tv_usec - used1.ru_stime.tv_usec) / 1e6);
+
+    printf("(%.2fs)\n", elapsed);
+
+    return fcnresult;
+}
diff --git a/check/inifcns_consist.cpp b/check/inifcns_consist.cpp
new file mode 100644 (file)
index 0000000..35baf29
--- /dev/null
@@ -0,0 +1,218 @@
+// check/inifcns_consist.cpp
+
+/* This test routine applies assorted tests on initially known higher level
+ * functions. */
+
+#include "ginac.h"
+
+/* Simple tests on the sine trigonometric function. */
+static unsigned inifcns_consist_sin(void)
+{
+    unsigned result = 0;
+    bool errorflag;
+    
+    // sin(n*Pi) == 0?
+    errorflag = false;
+    for (int n=-10; n<=10; ++n) {
+        if (  sin(n*Pi).eval() != numeric(0) ||
+             !sin(n*Pi).eval().info(info_flags::integer) )
+            errorflag = true;
+    }
+    if ( errorflag ) {
+        clog << "sin(n*Pi) with integer n does not always return exact 0"
+             << endl;
+        ++result;
+    }
+    
+    // sin((n+1/2)*Pi) == {+|-}1?
+    errorflag = false;
+    for (int n=-10; n<=10; ++n) {
+        if ( ! sin((n+numeric(1,2))*Pi).eval().info(info_flags::integer) ||
+             !(sin((n+numeric(1,2))*Pi).eval() == numeric(1) ||
+               sin((n+numeric(1,2))*Pi).eval() == numeric(-1)) )
+            errorflag = true;
+    }
+    if ( errorflag ) {
+        clog << "sin((n+1/2)*Pi) with integer n does not always return exact {+|-}1"
+             << endl;
+        ++result;
+    }
+    
+    return result;
+}
+
+/* Simple tests on the cosine trigonometric function. */
+static unsigned inifcns_consist_cos(void)
+{
+    unsigned result = 0;
+    bool errorflag;
+    
+    // cos((n+1/2)*Pi) == 0?
+    errorflag = false;
+    for (int n=-10; n<=10; ++n) {
+        if (  cos((n+numeric(1,2))*Pi).eval() != numeric(0) ||
+             !cos((n+numeric(1,2))*Pi).eval().info(info_flags::integer) )
+            errorflag = true;
+    }
+    if ( errorflag ) {
+        clog << "cos((n+1/2)*Pi) with integer n does not always return exact 0"
+             << endl;
+        ++result;
+    }
+    
+    // cos(n*Pi) == 0?
+    errorflag = false;
+    for (int n=-10; n<=10; ++n) {
+        if ( ! cos(n*Pi).eval().info(info_flags::integer) ||
+             !(cos(n*Pi).eval() == numeric(1) ||
+               cos(n*Pi).eval() == numeric(-1)) )
+            errorflag = true;
+    }
+    if ( errorflag ) {
+        clog << "cos(n*Pi) with integer n does not always return exact {+|-}1"
+             << endl;
+        ++result;
+    }
+    
+    return result;
+}
+
+/* Assorted tests on other transcendental functions. */
+static unsigned inifcns_consist_trans(void)
+{
+    unsigned result = 0;
+    symbol x("x");
+    ex chk;
+    
+    chk = asin(1)-acos(0);
+    if (!chk.is_zero()) {
+        clog << "asin(1)-acos(0) erroneously returned " << chk
+             << " instead of 0" << endl;
+        ++result;
+    }
+    
+    // arbitrary check of type sin(f(x)):
+    chk = pow(sin(acos(x)),2) + pow(sin(asin(x)),2)
+        - (1+pow(x,2))*pow(sin(atan(x)),2);
+    if (chk != 1-pow(x,2)) {
+        clog << "sin(acos(x))^2 + sin(asin(x))^2 - (1+x^2)*sin(atan(x))^2 "
+             << "erroneously returned " << chk << " instead of 1-x^2" << endl;
+        ++result;
+    }
+    
+    // arbitrary check of type cos(f(x)):
+    chk = pow(cos(acos(x)),2) + pow(cos(asin(x)),2)
+        - (1+pow(x,2))*pow(cos(atan(x)),2);
+    if (!chk.is_zero()) {
+        clog << "cos(acos(x))^2 + cos(asin(x))^2 - (1+x^2)*cos(atan(x))^2 "
+             << "erroneously returned " << chk << " instead of 0" << endl;
+        ++result;
+    }
+    
+    // arbitrary check of type tan(f(x)):
+    chk = tan(acos(x))*tan(asin(x)) - tan(atan(x));
+    if (chk != 1-x) {
+        clog << "tan(acos(x))*tan(asin(x)) - tan(atan(x)) "
+             << "erroneously returned " << chk << " instead of -x+1" << endl;
+        ++result;
+    }
+    
+    // arbitrary check of type sinh(f(x)):
+    chk = -pow(sinh(acosh(x)),2).expand()*pow(sinh(atanh(x)),2)
+        - pow(sinh(asinh(x)),2);
+    if (!chk.is_zero()) {
+        clog << "expand(-(sinh(acosh(x)))^2)*(sinh(atanh(x))^2) - sinh(asinh(x))^2 "
+             << "erroneously returned " << chk << " instead of 0" << endl;
+        ++result;
+    }
+    
+    // arbitrary check of type cosh(f(x)):
+    chk = (pow(cosh(asinh(x)),2) - 2*pow(cosh(acosh(x)),2))
+        * pow(cosh(atanh(x)),2);
+    if (chk != 1) {
+        clog << "(cosh(asinh(x))^2 - 2*cosh(acosh(x))^2) * cosh(atanh(x))^2 "
+             << "erroneously returned " << chk << " instead of 1" << endl;
+        ++result;
+    }
+    
+    // arbitrary check of type tanh(f(x)):
+    chk = (pow(tanh(asinh(x)),-2) - pow(tanh(acosh(x)),2)).expand()
+        * pow(tanh(atanh(x)),2);
+    if (chk != 2) {
+        clog << "expand(tanh(acosh(x))^2 - tanh(asinh(x))^(-2)) * tanh(atanh(x))^2 "
+             << "erroneously returned " << chk << " instead of 2" << endl;
+        ++result;
+    }
+    
+    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. */
+static unsigned inifcns_consist_gamma(void)
+{
+    unsigned result = 0;
+    ex e;
+    
+    e = gamma(ex(1));
+    for (int i=2; i<8; ++i) {
+        e += gamma(ex(i));
+    }
+    if ( e != numeric(874) ) {
+        clog << "gamma(1)+...+gamma(7) erroneously returned "
+             << e << " instead of 874" << endl;
+        ++result;
+    }
+    
+    e = gamma(ex(1));
+    for (int i=2; i<8; ++i) {
+        e *= gamma(ex(i));
+    }
+    if ( e != numeric(24883200) ) {
+        clog << "gamma(1)*...*gamma(7) erroneously returned "
+             << e << " instead of 24883200" << endl;
+        ++result;
+    }
+              
+    e = gamma(ex(numeric(5, 2)))*gamma(ex(numeric(9, 2)))*64;
+    if ( e != 315*Pi ) {
+        clog << "64*gamma(5/2)*gamma(9/2) erroneously returned "
+             << e << " instead of 315*Pi" << endl;
+        ++result;
+    }
+    
+    e = gamma(ex(numeric(-13, 2)));
+    for (int i=-13; i<7; i=i+2) {
+        e += gamma(ex(numeric(i, 2)));
+    }
+    e = (e*gamma(ex(numeric(15, 2)))*numeric(512));
+    if ( e != numeric(633935)*Pi ) {
+        clog << "512*(gamma(-13/2)+...+gamma(5/2))*gamma(15/2) erroneously returned "
+             << e << " instead of 633935*Pi" << endl;
+        ++result;
+    }
+    
+    return result;
+}
+
+unsigned inifcns_consist(void)
+{
+    unsigned result = 0;
+
+    cout << "checking consistency of symbolic functions..." << flush;
+    clog << "---------consistency of symbolic functions:" << endl;
+    
+    result += inifcns_consist_sin();
+    result += inifcns_consist_cos();
+    result += inifcns_consist_trans();
+    result += inifcns_consist_gamma();
+
+    if ( !result ) {
+        cout << " passed ";
+        clog << "(no output)" << endl;
+    } else {
+        cout << " failed ";
+    }
+    
+    return result;
+}
diff --git a/check/lsolve_onedim.cpp b/check/lsolve_onedim.cpp
new file mode 100644 (file)
index 0000000..d89722f
--- /dev/null
@@ -0,0 +1,33 @@
+// check/lsolve_onedim.cpp
+
+/* This test routine does some simple checks on solving a polynomial for a
+ * variable. */
+
+#include "ginac.h"
+
+unsigned lsolve_onedim(void)
+{
+    unsigned result = 0;
+    symbol x("x");
+    ex eq, aux;
+    
+    cout << "checking linear solve..." << flush;
+    clog << "---------linear solve:" << endl;
+    
+    eq = (3*x+5 == numeric(8));
+    aux = lsolve(eq,x);
+    if (aux != 1) {
+        result++;
+        clog << "solution of 3*x+5==8 erroneously returned "
+             << aux << endl;
+    }
+    
+    if (! result) {
+        cout << " passed ";
+        clog << "(no output)" << endl;
+    } else {
+        cout << " failed ";
+    }
+    
+    return result;
+}
diff --git a/check/main.cpp b/check/main.cpp
new file mode 100644 (file)
index 0000000..1440777
--- /dev/null
@@ -0,0 +1,41 @@
+// check/main.cpp
+
+#include "ginac.h"
+#include "check.h"
+
+int main()
+{
+    unsigned result = 0;
+    
+    try {
+        for (int i=0; i<1; ++i) {
+            result += fcntimer(paranoia_check);
+            result += fcntimer(numeric_output);
+            result += fcntimer(numeric_consist);
+            result += fcntimer(powerlaws);
+            result += fcntimer(expand_subs);
+            result += fcntimer(inifcns_consist);
+            result += fcntimer(differentiation);
+            result += fcntimer(poly_gcd);
+            result += fcntimer(normalization);
+            result += fcntimer(matrix_checks);
+            result += fcntimer(lsolve_onedim);
+            result += fcntimer(series_expansion);
+        }
+    } catch (exception const & e) {
+        cout << "error: caught an exception: " << e.what() << endl;
+    }
+    
+    if (result) {
+        cout << "error: something went wrong. ";
+        if (result == 1) {
+            cout << "(one failure)" << endl;
+        } else {
+            cout << "(" << result << " individual failures)" << endl;
+        }
+        cout << "please check result.out against result.ref for more details."
+             << endl << "happy debugging!" << endl;
+    }
+
+    return result;
+}
diff --git a/check/matrix_checks.cpp b/check/matrix_checks.cpp
new file mode 100644 (file)
index 0000000..1bf8e0c
--- /dev/null
@@ -0,0 +1,219 @@
+// check/matrix_checks.cpp
+
+/* Here we test manipulations on GiNaC's symbolic matrices. */
+
+#include "ginac.h"
+#include <stdexcept>
+
+static unsigned matrix_determinants(void)
+{
+    unsigned result = 0;
+    ex det;
+    matrix m1(1,1), m2(2,2), m3(3,3);
+    symbol a("a"), b("b"), c("c");
+    symbol d("d"), e("e"), f("f");
+    symbol g("g"), h("h"), i("i");
+    
+    // check symbolic trivial matrix determinant
+    m1.set(0,0,a);
+    det = m1.determinant();
+    if (det != a) {
+        clog << "determinant of 1x1 matrix " << m1
+             << " erroneously returned " << det << endl;
+        ++result;
+    }
+    
+    // check generic dense symbolic 2x2 matrix determinant
+    m2.set(0,0,a).set(0,1,b);
+    m2.set(1,0,c).set(1,1,d);
+    det = m2.determinant();
+    if (det != (a*d-b*c)) {
+        clog << "determinant of 2x2 matrix " << m2
+             << " erroneously returned " << det << endl;
+        ++result;
+    }
+    
+    // check generic dense symbolic 3x3 matrix determinant
+    m3.set(0,0,a).set(0,1,b).set(0,2,c);
+    m3.set(1,0,d).set(1,1,e).set(1,2,f);
+    m3.set(2,0,g).set(2,1,h).set(2,2,i);
+    det = m3.determinant().expand();
+    if (det != (a*e*i - a*f*h - d*b*i + d*c*h + g*b*f - g*c*e)) {
+        clog << "determinant of 3x3 matrix " << m3
+             << " erroneously returned " << det << endl;
+        ++result;
+    }
+    
+    // check dense numeric 3x3 matrix determinant
+    m3.set(0,0,numeric(0)).set(0,1,numeric(-1)).set(0,2,numeric(3));
+    m3.set(1,0,numeric(3)).set(1,1,numeric(-2)).set(1,2,numeric(2));
+    m3.set(2,0,numeric(3)).set(2,1,numeric(4)).set(2,2,numeric(-2));
+    det = m3.determinant();
+    if (det != 42) {
+        clog << "determinant of 3x3 matrix " << m3
+             << " erroneously returned " << det << endl;
+        ++result;
+    }
+    
+    // check dense symbolic 2x2 matrix determinant
+    m2.set(0,0,a/(a-b)).set(0,1,numeric(1));
+    m2.set(1,0,b/(a-b)).set(1,1,numeric(1));
+    det = m2.determinant(true);
+    if (det != 1) {
+        clog << "determinant of 2x2 matrix " << m2
+             << " erroneously returned " << det << endl;
+        ++result;
+    }
+
+    // check characteristic polynomial
+    m3.set(0,0,a).set(0,1,-2).set(0,2,2);
+    m3.set(1,0,3).set(1,1,a-1).set(1,2,2);
+    m3.set(2,0,3).set(2,1,4).set(2,2,a-3);
+    ex p = m3.charpoly(a);
+    if (p != 0) {
+        clog << "charpoly of 3x3 matrix " << m3
+             << " erroneously returned " << p << endl;
+        ++result;
+    }
+    
+    return result;
+}
+
+static unsigned matrix_invert1(void)
+{
+    matrix m(1,1);
+    symbol a("a");
+
+    m.set(0,0,a);
+    matrix m_i = m.inverse();
+    
+    if (m_i(0,0) != pow(a,-1)) {
+        clog << "inversion of 1x1 matrix " << m
+             << " erroneously returned " << m_i << endl;
+        return 1;
+    }
+    return 0;
+}
+
+static unsigned matrix_invert2(void)
+{
+    matrix m(2,2);
+    symbol a("a"), b("b"), c("c"), d("d");
+    m.set(0,0,a).set(0,1,b);
+    m.set(1,0,c).set(1,1,d);
+    matrix m_i = m.inverse();
+    ex det = m.determinant().expand();
+    
+    if ( (normal(m_i(0,0)*det) != d) ||
+         (normal(m_i(0,1)*det) != -b) ||
+         (normal(m_i(1,0)*det) != -c) ||
+         (normal(m_i(1,1)*det) != a) ) {
+        clog << "inversion of 2x2 matrix " << m
+             << " erroneously returned " << m_i << endl;
+        return 1;
+    }
+    return 0;
+}
+
+static unsigned matrix_invert3(void)
+{
+    matrix m(3,3);
+    symbol a("a"), b("b"), c("c");
+    symbol d("d"), e("e"), f("f");
+    symbol g("g"), h("h"), i("i");
+    m.set(0,0,a).set(0,1,b).set(0,2,c);
+    m.set(1,0,d).set(1,1,e).set(1,2,f);
+    m.set(2,0,g).set(2,1,h).set(2,2,i);
+    matrix m_i = m.inverse();
+    ex det = m.determinant().normal().expand();
+    
+    if ( (normal(m_i(0,0)*det) != (e*i-f*h)) ||
+         (normal(m_i(0,1)*det) != (c*h-b*i)) ||
+         (normal(m_i(0,2)*det) != (b*f-c*e)) ||
+         (normal(m_i(1,0)*det) != (f*g-d*i)) ||
+         (normal(m_i(1,1)*det) != (a*i-c*g)) ||
+         (normal(m_i(1,2)*det) != (c*d-a*f)) ||
+         (normal(m_i(2,0)*det) != (d*h-e*g)) ||
+         (normal(m_i(2,1)*det) != (b*g-a*h)) ||
+         (normal(m_i(2,2)*det) != (a*e-b*d)) ) {
+        clog << "inversion of 3x3 matrix " << m
+             << " erroneously returned " << m_i << endl;
+        return 1;
+    }
+    return 0;
+}
+
+static unsigned matrix_misc(void)
+{
+    unsigned result = 0;
+    matrix m1(2,2);
+    symbol a("a"), b("b"), c("c"), d("d"), e("e"), f("f");
+    m1.set(0,0,a).set(0,1,b);
+    m1.set(1,0,c).set(1,1,d);
+    ex tr = trace(m1);
+    
+    // check a simple trace
+    if (tr.compare(a+d)) {
+        clog << "trace of 2x2 matrix " << m1
+             << " erroneously returned " << tr << endl;
+        ++result;
+    }
+    
+    // and two simple transpositions
+    matrix m2 = transpose(m1);
+    if (m2(0,0) != a || m2(0,1) != c || m2(1,0) != b || m2(1,1) != d) {
+        clog << "transpose of 2x2 matrix " << m1
+             << " erroneously returned " << m2 << endl;
+        ++result;
+    }
+    matrix m3(3,2);
+    m3.set(0,0,a).set(0,1,b);
+    m3.set(1,0,c).set(1,1,d);
+    m3.set(2,0,e).set(2,1,f);
+    if (transpose(transpose(m3)) != m3) {
+        clog << "transposing 3x2 matrix " << m3 << " twice"
+             << " erroneously returned " << transpose(transpose(m3)) << endl;
+        ++result;
+    }
+    
+    // produce a runtime-error by inverting a singular matrix and catch it
+    matrix m4(2,2);
+    matrix m5;
+    bool caught=false;
+    try {
+        m5 = inverse(m4);
+    }
+    catch (std::runtime_error err) {
+        caught=true;
+    }
+    if (!caught) {
+        cerr << "singular 2x2 matrix " << m4
+             << " erroneously inverted to " << m5 << endl;
+        ++result;
+    }
+    
+    return result;
+}
+
+unsigned matrix_checks(void)
+{
+    unsigned result = 0;
+    
+    cout << "checking symbolic matrix manipulations..." << flush;
+    clog << "---------symbolic matrix manipulations:" << endl;
+    
+    result += matrix_determinants();
+    result += matrix_invert1();
+    result += matrix_invert2();
+    result += matrix_invert3();
+    result += matrix_misc();
+    
+    if (! result) {
+        cout << " passed ";
+        clog << "(no output)" << endl;
+    } else {
+        cout << " failed ";
+    }
+    
+    return result;
+}
diff --git a/check/normalization.cpp b/check/normalization.cpp
new file mode 100644 (file)
index 0000000..83befd8
--- /dev/null
@@ -0,0 +1,113 @@
+// check/normalization.cpp
+
+/* Rational function normalization test-suite. */
+
+#include "ginac.h"
+
+static symbol x("x"), y("y"), z("z");
+
+static unsigned check_normal(const ex &e, const ex &d)
+{
+       ex en = e.normal();
+       if (en.compare(d) != 0) {
+               clog << "normal form of " << e << " is " << en << " (should be " << d << ")" << endl;
+               return 1;
+       }
+       return 0;
+}
+
+static unsigned normal1(void)
+{
+       unsigned result = 0;
+       ex e, d;
+
+       // Expansion
+       e = pow(x, 2) - (x+1)*(x-1) - 1;
+       d = exZERO();
+       result += check_normal(e, d);
+
+       // Expansion inside functions
+       e = sin(x*(x+1)-x) + 1;
+       d = sin(pow(x, 2)) + 1;
+       result += check_normal(e, d);
+
+       // Fraction addition
+       e = numeric(2)/x + y/3;
+       d = (x*y/3 + 2) / x;
+       result += check_normal(e, d);
+
+       // Fraction addition
+       e = pow(x, -1) + x/(x+1);
+       d = (pow(x, 2)+x+1)/(x*(x+1));
+       result += check_normal(e, d);
+
+       // Fraction cancellation
+       e = (pow(x, 2) - pow(y, 2)) / pow(x-y, 3);
+       d = (x + y) / (pow(x, 2) + pow(y, 2) - x * y * 2);
+       result += check_normal(e, d);
+
+       // Fraction cancellation
+       e = (pow(x, -1) + x) / (pow(x , 2) * 2 + 2);
+       d = pow(x * 2, -1);
+       result += check_normal(e, d);
+
+       // Distribution of powers
+       e = pow(x/y, 2);
+       d = pow(x, 2) / pow(y, 2);
+       result += check_normal(e, d);
+
+       // Distribution of powers (integer, distribute) and fraction addition
+       e = pow(pow(x, -1) + x, 2);
+       d = pow(pow(x, 2) + 1, 2) / pow(x, 2);
+       result += check_normal(e, d);
+
+       // Distribution of powers (non-integer, don't distribute) and fraction addition
+       e = pow(pow(x, -1) + x, numeric(1)/2);
+       d = pow((pow(x, 2) + 1) / x, numeric(1)/2);
+       result += check_normal(e, d);
+
+       // Replacement of functions with temporary symbols and fraction cancellation
+       e = pow(sin(x), 2) - pow(cos(x), 2);
+       e /= sin(x) + cos(x);
+       d = sin(x) - cos(x);
+       result += check_normal(e, d);
+
+       // Replacement of non-integer powers with temporary symbols
+       e = (pow(numeric(2), numeric(1)/2) * x + x) / x;
+       d = pow(numeric(2), numeric(1)/2) + 1;
+       result += check_normal(e, d);
+
+       // Replacement of complex numbers with temporary symbols
+       e = (x + y + x*I + y*I) / (x + y);
+       d = 1 + I;
+       result += check_normal(e, d);
+
+       e = (pow(x, 2) + pow(y, 2)) / (x + y*I);
+       d = e;
+       result += check_normal(e, d);
+
+       // More complex rational function
+       e = (pow(x-y*2,4)/pow(pow(x,2)-pow(y,2)*4,2)+1)*(x+y*2)*(y+z)/(pow(x,2)+pow(y,2)*4);
+       d = (y*2 + z*2) / (x + y*2);
+       result += check_normal(e, d);
+
+       return result;
+}
+
+unsigned normalization(void)
+{
+       unsigned result = 0;
+
+       cout << "checking rational function normalization..." << flush;
+       clog << "---------rational function normalization:" << endl;
+
+       result += normal1();
+
+       if (!result) {
+               cout << " passed ";
+               clog << "(no output)" << endl;
+       } else {
+               cout << " failed ";
+       }
+       return result;
+}
diff --git a/check/numeric_consist.cpp b/check/numeric_consist.cpp
new file mode 100644 (file)
index 0000000..d7a5b6b
--- /dev/null
@@ -0,0 +1,316 @@
+// check/numeric_consist.cpp
+
+/* This test routine creates some numbers and check the result of several
+ * boolean tests on these numbers like is_integer() etc... */
+
+#include "ginac.h"
+#include <stdlib.h>
+
+/* Simple and maybe somewhat pointless consistency tests of assorted tests and
+ * conversions. */
+static unsigned numeric_consist1(void)
+{
+    unsigned result = 0;
+    numeric test_int1(42);
+    numeric test_int2(5);
+    numeric test_rat1 = test_int1; test_rat1 /= test_int2;
+    test_rat1 = -test_rat1;         // -42/5
+    symbol a("a");
+    ex e1, e2;
+    
+    if ( !test_int1.is_integer() ) {
+        clog << test_int1
+             << " erroneously not recognized as integer" << endl;
+        ++result;
+    }
+    if ( !test_int1.is_rational() ) {
+        clog << test_int1
+             << " erroneously not recognized as rational" << endl;
+        ++result;
+    }
+    
+    if ( !test_rat1.is_rational() ) {
+        clog << test_rat1
+             << " erroneously not recognized as rational" << endl;
+        ++result;
+    }
+    if ( test_rat1.is_integer() ) {
+        clog << test_rat1
+             << " erroneously recognized as integer" << endl;
+        ++result;
+    }
+    
+    int i = numeric(1984).to_int();
+    if ( i-1984 ) {
+        clog << "conversion of " << i
+             << " from numeric to int failed" << endl;
+        ++result;
+    }
+    
+    e1 = test_int1;
+    if ( !e1.info(info_flags::posint) ) {
+        clog << "expression " << e1
+             << " erroneously not recognized as positive integer" << endl;
+        ++result;
+    }
+    
+    e2 = test_int1 + a;
+    if ( ex_to_numeric(e2).is_integer() ) {
+        clog << "expression " << e2
+             << " erroneously recognized as integer" << endl;
+        ++result;
+    }
+    
+    // The next two were two actual bugs in CLN till June, 12, 1999:
+    test_rat1 = numeric(3)/numeric(2);
+    test_rat1 += test_rat1;
+    if ( !test_rat1.is_integer() ) {
+        clog << "3/2 + 3/2 erroneously not integer 3 but instead "
+             << test_rat1 << endl;
+        ++result;
+    }
+    test_rat1 = numeric(3)/numeric(2);
+    numeric test_rat2 = test_rat1 + numeric(1);  // 5/2
+    test_rat2 -= test_rat1;             // 1
+    if ( !test_rat2.is_integer() ) {
+        clog << "5/2 - 3/2 erroneously not integer 1 but instead "
+             << test_rat2 << endl;
+        ++result;
+    }
+    
+    // Check some numerator and denominator calculations:
+    for (int i=0; i<10; ++i) {
+        int re_q, im_q;
+        do { re_q = rand(); } while (re_q == 0);
+        do { im_q = rand(); } while (im_q == 0);
+        numeric r(rand()-RAND_MAX/2, re_q);
+        numeric i(rand()-RAND_MAX/2, im_q);
+        numeric z = r + I*i;
+        numeric p = numer(z);
+        numeric q = denom(z);
+        numeric res = p/q;
+        if (res != z) {
+            clog << z << " erroneously transformed into " 
+                 << p << "/" << q << " by numer() and denom()" << endl;
+            ++result;
+        }
+    }    
+    return result;
+}
+
+/* We had some fun with a bug in CLN that caused it to loop forever when
+ * calculating expt(a,b) if b is a rational and a a nonnegative integer.
+ * Implementing a workaround sadly introduced another bug on May 28th 1999
+ * that was fixed on May 31st.  The workaround turned out to be stupid and
+ * the bug was finally killed in CLN on September 2nd. */
+static unsigned numeric_consist2(void)
+{
+    unsigned result = 0;
+    
+    ex zero = numeric(0);
+    ex two = numeric(2);
+    ex three = numeric(3);
+    
+    // The hang in this code was the reason for the original workaround
+    if ( pow(two,two/three) == 42 ) {
+        clog << "pow(2,2/3) erroneously returned 42" << endl;
+        ++result;  // cannot happen
+    }
+    
+    // Actually, this used to raise a FPE after introducing the workaround
+    if ( two*zero != zero ) {
+        clog << "2*0 erroneously returned " << two*zero << endl;
+        ++result;
+    }
+    
+    // And this returned a cl_F due to the implicit call of numeric::power()
+    ex six = two*three;
+    if ( !six.info(info_flags::integer) ) {
+        clog << "2*3 erroneously returned the non-integer " << six << endl;
+        ++result;
+    }
+    
+    // The fix in the workaround left a whole which was fixed hours later...
+    ex another_zero = pow(zero,numeric(1)/numeric(2));
+    if ( another_zero.compare(exZERO()) ) {
+        clog << "pow(0,1/2) erroneously returned" << another_zero << endl;
+        ++result;
+    }
+    
+    return result;
+}
+
+/* Assorted tests to ensure some crucial functions behave exactly as specified
+ * in the documentation. */
+static unsigned numeric_consist3(void)
+{
+    unsigned result = 0;
+    numeric calc_rem, calc_quo;
+    numeric a, b;
+    
+    // check if irem(a, b) and irem(a, b, q) really behave like Maple's 
+    // irem(a, b) and irem(a, b, 'q') as advertised in our documentation.
+    // These overloaded routines indeed need to be checked separately since
+    // internally they might be doing something completely different:
+    a = 23; b = 4; calc_rem = irem(a, b);
+    if ( calc_rem != 3 ) {
+        clog << "irem(" << a << "," << b << ") erroneously returned "
+             << calc_rem << endl;
+        ++result;
+    }
+    a = 23; b = -4; calc_rem = irem(a, b);
+    if ( calc_rem != 3 ) {
+        clog << "irem(" << a << "," << b << ") erroneously returned "
+             << calc_rem << endl;
+        ++result;
+    }
+    a = -23; b = 4; calc_rem = irem(a, b);
+    if ( calc_rem != -3 ) {
+        clog << "irem(" << a << "," << b << ") erroneously returned "
+             << calc_rem << endl;
+        ++result;
+    }
+    a = -23; b = -4; calc_rem = irem(a, b);
+    if ( calc_rem != -3 ) {
+        clog << "irem(" << a << "," << b << ") erroneously returned "
+             << calc_rem << endl;
+        ++result;
+    }
+    // and now the overloaded irem(a,b,q):
+    a = 23; b = 4; calc_rem = irem(a, b, calc_quo);
+    if ( calc_rem != 3 || calc_quo != 5 ) {
+        clog << "irem(" << a << "," << b << ",q) erroneously returned "
+             << calc_rem << " with q=" << calc_quo << endl;
+        ++result;
+    }
+    a = 23; b = -4; calc_rem = irem(a, b, calc_quo);
+    if ( calc_rem != 3 || calc_quo != -5 ) {
+        clog << "irem(" << a << "," << b << ",q) erroneously returned "
+             << calc_rem << " with q=" << calc_quo << endl;
+        ++result;
+    }
+    a = -23; b = 4; calc_rem = irem(a, b, calc_quo);
+    if ( calc_rem != -3 || calc_quo != -5 ) {
+        clog << "irem(" << a << "," << b << ",q) erroneously returned "
+             << calc_rem << " with q=" << calc_quo << endl;
+        ++result;
+    }
+    a = -23; b = -4; calc_rem = irem(a, b, calc_quo);
+    if ( calc_rem != -3 || calc_quo != 5 ) {
+        clog << "irem(" << a << "," << b << ",q) erroneously returned "
+             << calc_rem << " with q=" << calc_quo << endl;
+        ++result;
+    }
+    // check if iquo(a, b) and iquo(a, b, r) really behave like Maple's 
+    // iquo(a, b) and iquo(a, b, 'r') as advertised in our documentation.
+    // These overloaded routines indeed need to be checked separately since
+    // internally they might be doing something completely different:
+    a = 23; b = 4; calc_quo = iquo(a, b);
+    if ( calc_quo != 5 ) {
+        clog << "iquo(" << a << "," << b << ") erroneously returned "
+             << calc_quo << endl;
+        ++result;
+    }
+    a = 23; b = -4; calc_quo = iquo(a, b);
+    if ( calc_quo != -5 ) {
+        clog << "iquo(" << a << "," << b << ") erroneously returned "
+             << calc_quo << endl;
+        ++result;
+    }
+    a = -23; b = 4; calc_quo = iquo(a, b);
+    if ( calc_quo != -5 ) {
+        clog << "iquo(" << a << "," << b << ") erroneously returned "
+             << calc_quo << endl;
+        ++result;
+    }
+    a = -23; b = -4; calc_quo = iquo(a, b);
+    if ( calc_quo != 5 ) {
+        clog << "iquo(" << a << "," << b << ") erroneously returned "
+             << calc_quo << endl;
+        ++result;
+    }
+    // and now the overloaded iquo(a,b,r):
+    a = 23; b = 4; calc_quo = iquo(a, b, calc_rem);
+    if ( calc_quo != 5 || calc_rem != 3 ) {
+        clog << "iquo(" << a << "," << b << ",r) erroneously returned "
+             << calc_quo << " with r=" << calc_rem << endl;
+        ++result;
+    }
+    a = 23; b = -4; calc_quo = iquo(a, b, calc_rem);
+    if ( calc_quo != -5 || calc_rem != 3 ) {
+        clog << "iquo(" << a << "," << b << ",r) erroneously returned "
+             << calc_quo << " with r=" << calc_rem << endl;
+        ++result;
+    }
+    a = -23; b = 4; calc_quo = iquo(a, b, calc_rem);
+    if ( calc_quo != -5 || calc_rem != -3 ) {
+        clog << "iquo(" << a << "," << b << ",r) erroneously returned "
+             << calc_quo << " with r=" << calc_rem << endl;
+        ++result;
+    }
+    a = -23; b = -4; calc_quo = iquo(a, b, calc_rem);
+    if ( calc_quo != 5 || calc_rem != -3 ) {
+        clog << "iquo(" << a << "," << b << ",r) erroneously returned "
+             << calc_quo << " with r=" << calc_rem << endl;
+        ++result;
+    }
+    
+    return result;
+}
+
+/* Now we perform some less trivial checks about several functions which should
+ * return exact numbers if possible. */
+static unsigned numeric_consist4(void)
+{
+    unsigned result = 0;
+    bool passed;
+    
+    // square roots of squares of integers:
+    passed = true;
+    for (int i=0; i<42; ++i) {
+        if ( !sqrt(numeric(i*i)).is_integer() ) {
+            passed = false;
+        }
+    }
+    if ( !passed ) {
+        clog << "One or more square roots of squares of integers did not return exact integers" << endl;
+        ++result;
+    }
+    // square roots of squares of rationals:
+    passed = true;
+    for (int num=0; num<41; ++num) {
+        for (int den=1; den<42; ++den) {
+            if ( !sqrt(numeric(num*num)/numeric(den*den)).is_rational() ) {
+                passed = false;
+            }
+        }
+    }
+    if ( !passed ) {
+        clog << "One or more square roots of squares of rationals did not return exact integers" << endl;
+        ++result;
+    }
+    
+    return result;
+}
+
+unsigned numeric_consist(void)
+{
+    unsigned result = 0;
+
+    cout << "checking consistency of numeric types..." << flush;
+    clog << "---------consistency of numeric types:" << endl;
+    
+    result += numeric_consist1();
+    result += numeric_consist2();
+    result += numeric_consist3();
+    result += numeric_consist4();
+
+    if ( !result ) {
+        cout << " passed ";
+        clog << "(no output)" << endl;
+    } else {
+        cout << " failed ";
+    }
+    
+    return result;
+}
diff --git a/check/numeric_output.cpp b/check/numeric_output.cpp
new file mode 100644 (file)
index 0000000..f010ab7
--- /dev/null
@@ -0,0 +1,37 @@
+// check/numeric_output.cpp
+
+#include "ginac.h"
+
+unsigned numeric_output(void)
+{
+    unsigned result = 0;
+    
+    cout << "checking output of numeric types..." << flush;
+    clog << "---------output of numeric types:" << endl;
+    
+    unsigned long Digits_before = Digits;
+    Digits = 200;
+    clog << "Using " << Digits << " digits" << endl;
+    clog << Pi << " evalfs to: " << Pi.evalf() << endl;
+    clog << Catalan << " evalfs to: " << Catalan.evalf() << endl;
+    clog << EulerGamma << " evalfs to: " << EulerGamma.evalf() << endl;
+    clog << "Complex integers: ";
+    clog << "{(0,0)=" << ex(0 + 0*I) << "} ";
+    clog << "{(1,0)=" << ex(1 + 0*I) << "} ";
+    clog << "{(1,1)=" << ex(1 + 1*I) << "} ";
+    clog << "{(0,1)=" << ex(0 + 1*I) << "} ";
+    clog << "{(-1,1)=" << ex(-1 + 1*I) << "} ";
+    clog << "{(-1,0)=" << ex(-1 + 0*I) << "} ";
+    clog << "{(-1,-1)=" << ex(-1 - 1*I) << "} ";
+    clog << "{(0,-1)=" << ex(0 - 1*I) << "} ";
+    clog << "{(1,-1)=" << ex(1 - 1*I) << "} " << endl;
+    Digits = Digits_before;
+    
+    if (! result) {
+        cout << " passed ";
+    } else {
+        cout << " failed ";
+    }
+    
+    return result;
+}
diff --git a/check/paranoia_check.cpp b/check/paranoia_check.cpp
new file mode 100644 (file)
index 0000000..bc66dea
--- /dev/null
@@ -0,0 +1,230 @@
+// check/paranoia_check.cpp
+
+/* This set of tests checks for some of GiNaC's oopses which showed up during
+ * development.  Things were evaluated wrongly and so.  It should not find such
+ * a sick behaviour again.  But since we are paranoic and we want to exclude
+ * that behaviour for good... */
+
+#include "ginac.h"
+
+// 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
+// introduced the second.)
+static unsigned paranoia_check1(void)
+{
+    unsigned result = 0;
+    symbol x("x"), y("y"), z("z");
+    ex e, f, g;
+
+    e = x * y * z;
+    f = y * z;
+    g = e / f;
+
+    // In the first one expand did not do any job at all:
+    if ( !g.expand().is_equal(x) ) {
+        clog << "e = x*y*z; f = y*z; expand(e/f) erroneously returned "
+             << g.expand() << endl;
+        ++result;
+    }
+
+    // This one somehow used to return 0:
+    e = pow(x + 1, -1);
+    if (!e.expand().is_equal(e)) {
+        clog << "expand(pow(x + 1, -1)) erroneously returned "
+             << e.expand() << endl;
+        ++result;
+    }
+
+    return result;
+}
+
+// And here the second oops which showed up until May 17th 1999.  It had to do
+// with lexicographic canonicalization and thus showed up only if the variables
+// had the names as given here:
+static unsigned paranoia_check2(void)
+{
+    unsigned result = 0;
+    symbol x("x"), y("y"), z("z");
+    ex e, f, g;
+
+    e = x + z*x;
+    f = e*y;
+    g = f - e*y;
+
+    // After .expand(), g should be zero:
+    if (!g.expand().is_equal(exZERO())) {
+        clog << "e = (x + z*x); f = e*y; expand(f - e*y) erroneously returned "
+             << g.expand() << endl;
+        ++result;
+    }
+    // After .eval(), g should be zero:
+    if (!g.eval().is_equal(exZERO())) {
+        clog << "e = (x + z*x); f = e*y; eval(f - e*y) erroneously returned "
+             << g.eval() << endl;
+        ++result;
+    }
+    // This actually worked already back in April.  But we are very paranoic!
+    if (!g.expand().eval().is_equal(exZERO())) {
+        clog << "e = (x + z*x); f = e*y; eval(expand(f - e*y)) erroneously returned "
+             << g.expand().eval() << endl;
+        ++result;
+    }
+
+    return result;
+}
+
+// The third bug was introduced on May 18, discovered on May 19 and fixed that
+// same day.  It worked when x was substituted by 1 but not with other numbers:
+static unsigned paranoia_check3(void)
+{
+    unsigned result = 0;
+    symbol x("x"), y("y");
+    ex e, f;
+
+    e = x*y - y;
+    f = e.subs(x == 2);
+
+    if (!f.is_equal(y)) {
+        clog << "e = x*y - y; f = e.subs(x == 2) erroneously returned "
+             << f << endl;
+        ++result;
+    }
+    if (!f.eval().is_equal(y)) {
+        clog << "e = x*y - y; eval(e.subs(x == 2)) erroneously returned "
+             << f.eval() << endl;
+        ++result;
+    }
+    if (!f.expand().is_equal(y)) {
+        clog << "e = x*y - y; expand(e.subs(x == 2)) erroneously returned "
+             << f.expand() << endl;
+        ++result;
+    }
+
+    return result;
+}
+
+// The fourth bug was also discovered on May 19 and fixed immediately:
+static unsigned paranoia_check4(void)
+{
+    unsigned result = 0;
+    symbol x("x");
+    ex e, f, g;
+
+    e = pow(x, 2) + x + 1;
+    f = pow(x, 2) + x + 1;
+    g = e - f;
+
+    if (!g.is_equal(exZERO())) {
+        clog << "e = pow(x,2) + x + 1; f = pow(x,2) + x + 1; g = e-f; g erroneously returned "
+             << g << endl;
+        ++result;
+    }
+    if (!g.is_equal(exZERO())) {
+        clog << "e = pow(x,2) + x + 1; f = pow(x,2) + x + 1; g = e-f; g.eval() erroneously returned "
+             << g.eval() << endl;
+        ++result;
+    }
+
+    return result;
+}
+
+// The fifth oops was discovered on May 20 and fixed a day later:
+static unsigned paranoia_check5(void)
+{
+    unsigned result = 0;
+    symbol x("x"), y("y");
+
+    ex e, f;
+    e = pow(x*y + 1, 2);
+    f = pow(x, 2) * pow(y, 2) + 2*x*y + 1;
+
+    if (!(e-f).expand().is_equal(exZERO())) {
+        clog << "e = pow(x*y+1,2); f = pow(x,2)*pow(y,2) + 2*x*y + 1; (e-f).expand() erroneously returned "
+             << (e-f).expand() << endl;
+        ++result;
+    }
+
+    return result;
+}
+
+// This one was discovered on Jun 1 and fixed the same day:
+static unsigned paranoia_check6(void)
+{
+    unsigned result = 0;
+    symbol x("x");
+
+    ex e, f;
+    e = pow(x, -5);
+    f = e.denom();
+
+    if (!f.is_equal(pow(x, 5))) {
+        clog << "e = pow(x, -5); f = e.denom(); f was " << f << " (should be x^5)" << endl;
+        ++result;
+    }
+    return result;
+}
+
+// This one was introduced on June 1 by some aggressive manual optimization.
+// Discovered and fixed on June 2.
+static unsigned paranoia_check7(void)
+{
+    unsigned result = 0;
+    symbol x("x"), y("y");
+
+    ex e = y + y*x + 2;
+    ex f = expand(pow(e, 2) - (e*y*(x + 1)));
+
+    if (f.nops() > 3) {
+        clog << "e=y+y*x+2; f=expand(pow(e,2)-(e*y*(x+1))) has "
+             << f.nops() << " arguments instead of 3 ( f=="
+             << f << " )" << endl;
+        ++result;
+    }
+    return result;
+}
+
+// This one was a result of the rewrite of mul::max_coefficient when we
+// introduced the overall_coefficient field in expairseq objects on Oct 1.
+// Fixed on Oct 4.
+static unsigned paranoia_check8(void)
+{
+    unsigned result = 0;
+    symbol x("x");
+
+    ex e = -x / (x+1);
+    ex f = e.normal();
+
+    // The bug caused a division by zero in normal(), so the following
+    // check is actually bogus...
+    if (!f.is_equal(e)) {
+        clog << "normal(-x/(x+1)) returns " << f << " instead of -x/(x+1)\n";
+        ++result;
+    }
+    return result;
+}
+
+unsigned paranoia_check(void)
+{
+    unsigned result = 0;
+
+    cout << "checking several ex-bugs just out of pure paranoia..." << flush;
+    clog << "---------several ex-bugs just out of pure paranoia:" << endl;
+
+    result += paranoia_check1();
+    result += paranoia_check2();
+    result += paranoia_check3();
+    result += paranoia_check4();
+    result += paranoia_check5();
+    result += paranoia_check6();
+    result += paranoia_check7();
+    result += paranoia_check8();
+
+    if (! result) {
+        cout << " passed ";
+        clog << "(no output)" << endl;
+    } else {
+        cout << " failed ";
+    }
+
+    return result;
+}
diff --git a/check/poly_gcd.cpp b/check/poly_gcd.cpp
new file mode 100644 (file)
index 0000000..6f81f6a
--- /dev/null
@@ -0,0 +1,238 @@
+// check/poly_gcd.cpp
+
+/* Some test with polynomial GCD calculations. See also the checks for
+ * rational function normalization in normalization.cpp. */
+
+#include "ginac.h"
+
+const int MAX_VARIABLES = 5;
+
+static symbol x("x"), z("z");
+static symbol y[MAX_VARIABLES];
+
+// GCD = 1
+static unsigned poly_gcd1(void)
+{
+       for (int v=1; v<=MAX_VARIABLES; v++) {
+               ex e1 = x;
+               ex e2 = pow(x, 2);
+               for (int i=0; i<v; i++) {
+                       e1 += y[i];
+                       e2 += pow(y[i], 2);
+               }
+
+               ex f = (e1 + 1) * (e1 + 2);
+               ex g = e2 * (-pow(x, 2) * y[0] * 3 + pow(y[0], 2) - 1);
+               ex r = gcd(f, g);
+               if (r != exONE()) {
+                       clog << "case 1, gcd(" << f << "," << g << ") = " << r << " (should be 1)" << endl;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+// Linearly dense quartic inputs with quadratic GCDs
+static unsigned poly_gcd2(void)
+{
+       for (int v=1; v<=MAX_VARIABLES; v++) {
+               ex e1 = x;
+               ex e2 = x;
+               for (int i=0; i<v; i++) {
+                       e1 += y[i];
+                       e2 -= y[i];
+               }
+
+               ex d = pow(e1 + 1, 2);
+               ex f = d * pow(e2 - 2, 2);
+               ex g = d * pow(e1 + 2, 2);
+               ex r = gcd(f, g);
+        ex re=r.expand();
+        ex df1=r-d;
+        ex df=(r-d).expand();
+               if ((r - d).expand().compare(exZERO()) != 0) {
+                       clog << "case 2, gcd(" << f << "," << g << ") = " << r << " (should be " << d << ")" << endl;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+// Sparse GCD and inputs where degrees are proportional to the number of variables
+static unsigned poly_gcd3(void)
+{
+       for (int v=1; v<=MAX_VARIABLES; v++) {
+               ex e1 = pow(x, v + 1);
+               for (int i=0; i<v; i++)
+                       e1 += pow(y[i], v + 1);
+
+               ex d = e1 + 1;
+               ex f = d * (e1 - 2);
+               ex g = d * (e1 + 2);
+               ex r = gcd(f, g);
+               if ((r - d).expand().compare(exZERO()) != 0) {
+                       clog << "case 3, gcd(" << f << "," << g << ") = " << r << " (should be " << d << ")" << endl;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+// Variation of case 3; major performance degradation with PRS
+static unsigned poly_gcd3p(void)
+{
+       for (int v=1; v<=MAX_VARIABLES; v++) {
+               ex e1 = pow(x, v + 1);
+               ex e2 = pow(x, v);
+               for (int i=0; i<v; i++) {
+                       e1 += pow(y[i], v + 1);
+                       e2 += pow(y[i], v);
+               }
+
+               ex d = e1 + 1;
+               ex f = d * (e1 - 2);
+               ex g = d * (e2 + 2);
+               ex r = gcd(f, g);
+               if ((r - d).expand().compare(exZERO()) != 0) {
+                       clog << "case 3p, gcd(" << f << "," << g << ") = " << r << " (should be " << d << ")" << endl;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+// Quadratic non-monic GCD; f and g have other quadratic factors
+static unsigned poly_gcd4(void)
+{
+       for (int v=1; v<=MAX_VARIABLES; v++) {
+               ex e1 = pow(x, 2) * pow(y[0], 2);
+               ex e2 = pow(x, 2) - pow(y[0], 2);
+               ex e3 = x * y[0];
+               for (int i=1; i<v; i++) {
+                       e1 += pow(y[i], 2);
+                       e2 += pow(y[i], 2);
+                       e3 += y[i];
+               }
+
+               ex d = e1 + 1;
+               ex f = d * (e2 - 1);
+               ex g = d * pow(e3 + 2, 2);
+               ex r = gcd(f, g);
+               if ((r - d).expand().compare(exZERO()) != 0) {
+                       clog << "case 4, gcd(" << f << "," << g << ") = " << r << " (should be " << d << ")" << endl;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+// Completely dense non-monic quadratic inputs with dense non-monic linear GCDs
+static unsigned poly_gcd5(void)
+{
+       for (int v=1; v<=MAX_VARIABLES; v++) {
+               ex e1 = x + 1;
+               ex e2 = x - 2;
+               ex e3 = x + 2;
+               for (int i=0; i<v; i++) {
+                       e1 *= y[i] + 1;
+                       e2 *= y[i] - 2;
+                       e3 *= y[i] + 2;
+               }
+
+               ex d = e1 - 3;
+               ex f = d * (e2 + 3);
+               ex g = d * (e3 - 3);
+               ex r = gcd(f, g);
+               if ((r - d).expand().compare(exZERO()) != 0) {
+                       clog << "case 5, gcd(" << f << "," << g << ") = " << r << " (should be " << d << ")" << endl;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+// Sparse non-monic quadratic inputs with linear GCDs
+static unsigned poly_gcd5p(void)
+{
+       for (int v=1; v<=MAX_VARIABLES; v++) {
+               ex e1 = x;
+               for (int i=0; i<v; i++)
+                       e1 *= y[i];
+
+               ex d = e1 - 1;
+               ex f = d * (e1 + 3);
+               ex g = d * (e1 - 3);
+               ex r = gcd(f, g);
+               if ((r - d).expand().compare(exZERO()) != 0) {
+                       clog << "case 5p, gcd(" << f << "," << g << ") = " << r << " (should be " << d << ")" << endl;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+// Trivariate inputs with increasing degrees
+static unsigned poly_gcd6(void)
+{
+       symbol y("y");
+
+       for (int j=1; j<=MAX_VARIABLES; j++) {
+               ex d = pow(x, j) * y * (z - 1);
+               ex f = d * (pow(x, j) + pow(y, j + 1) * pow(z, j) + 1);
+               ex g = d * (pow(x, j + 1) + pow(y, j) * pow(z, j + 1) - 7);
+               ex r = gcd(f, g);
+               if ((r - d).expand().compare(exZERO()) != 0) {
+                       clog << "case 6, gcd(" << f << "," << g << ") = " << r << " (should be " << d << ")" << endl;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+// Trivariate polynomials whose GCD has common factors with its cofactors
+static unsigned poly_gcd7(void)
+{
+       symbol y("y");
+       ex p = x - y * z + 1;
+       ex q = x - y + z * 3;
+
+       for (int j=1; j<=3; j++) {
+               for (int k=j+1; k<=4; k++) {
+                       ex d = pow(p, j) * pow(q, j);
+                       ex f = pow(p, j) * pow(q, k);
+                       ex g = pow(p, k) * pow(q, j); 
+                       ex r = gcd(f, g);
+                       if ((r - d).expand().compare(exZERO()) != 0 && (r + d).expand().compare(exZERO()) != 0) {
+                               clog << "case 7, gcd(" << f << "," << g << ") = " << r << " (should be " << d << ")" << endl;
+                               return 1;
+                       }
+               }
+       }
+       return 0;
+}
+
+unsigned poly_gcd(void)
+{
+    unsigned result = 0;
+
+       cout << "checking polynomial GCD computation..." << flush;
+       clog << "---------polynomial GCD computation:" << endl;
+
+       result += poly_gcd1();
+       result += poly_gcd2();
+       result += poly_gcd3();
+//     result += poly_gcd3p(); // takes extremely long (PRS "worst" case)
+       result += poly_gcd4();
+       result += poly_gcd5();
+       result += poly_gcd5p();
+       result += poly_gcd6();
+       result += poly_gcd7();
+
+       if (!result) {
+               cout << " passed ";
+        clog << "(no output)" << endl;
+    } else {
+               cout << " failed ";
+    }
+       return result;
+}
diff --git a/check/powerlaws.cpp b/check/powerlaws.cpp
new file mode 100644 (file)
index 0000000..9177dd7
--- /dev/null
@@ -0,0 +1,264 @@
+// check/powerlaws.cpp
+
+/* Tests for power laws.  You shouldn't try to draw much inspiration from
+ * this code, it is a sanity check rather deeply rooted in GiNaC's classes. */
+
+#include "ginac.h"
+
+static unsigned powerlaws1(void)
+{
+    // (x^a)^b = x^(a*b)
+    
+    symbol x("x");
+    symbol a("a");
+    symbol b("b");
+    
+    ex e1=power(power(x,a),b);
+    if (!(is_ex_exactly_of_type(e1,power) &&
+          is_ex_exactly_of_type(e1.op(0),power) &&
+          is_ex_exactly_of_type(e1.op(0).op(0),symbol) &&
+          is_ex_exactly_of_type(e1.op(0).op(1),symbol) &&
+          is_ex_exactly_of_type(e1.op(1),symbol) &&
+          e1.is_equal(power(power(x,a),b)) )) {
+        clog << "(x^a)^b, x,a,b symbolic wrong" << endl;
+        clog << "returned: " << e1 << endl;
+        return 1;
+    }
+    
+    ex e2=e1.subs(a==1);
+    if (!(is_ex_exactly_of_type(e2,power) &&
+          is_ex_exactly_of_type(e2.op(0),symbol) &&
+          is_ex_exactly_of_type(e2.op(1),symbol) &&
+          e2.is_equal(power(x,b)) )) {
+        clog << "(x^a)^b, x,b symbolic, a==1 wrong" << endl;
+        clog << "returned: " << e2 << endl;
+        return 1;
+    }
+    
+    ex e3=e1.subs(a==-1);
+    if (!(is_ex_exactly_of_type(e3,power) &&
+          is_ex_exactly_of_type(e3.op(0),power) &&
+          is_ex_exactly_of_type(e3.op(0).op(0),symbol) &&
+          is_ex_exactly_of_type(e3.op(0).op(1),numeric) &&
+          is_ex_exactly_of_type(e3.op(1),symbol) &&
+          e3.is_equal(power(power(x,-1),b)) )) {
+        clog << "(x^a)^b, x,b symbolic, a==-1 wrong" << endl;
+        clog << "returned: " << e3 << endl;
+        return 1;
+    }
+    
+    ex e4=e1.subs(lst(a==-1,b==2.5));
+    if (!(is_ex_exactly_of_type(e4,power) &&
+          is_ex_exactly_of_type(e4.op(0),power) &&
+          is_ex_exactly_of_type(e4.op(0).op(0),symbol) &&
+          is_ex_exactly_of_type(e4.op(0).op(1),numeric) &&
+          is_ex_exactly_of_type(e4.op(1),numeric) &&
+          e4.is_equal(power(power(x,-1),2.5)) )) {
+        clog << "(x^a)^b, x symbolic, a==-1, b==2.5 wrong" << endl;
+        clog << "returned: " << e4 << endl;
+        return 1;
+    }
+    
+    ex e5=e1.subs(lst(a==-0.9,b==2.5));
+    if (!(is_ex_exactly_of_type(e5,power) &&
+          is_ex_exactly_of_type(e5.op(0),symbol) &&
+          is_ex_exactly_of_type(e5.op(1),numeric) &&
+          e5.is_equal(power(x,numeric(-0.9)*numeric(2.5))) )) {
+        clog << "(x^a)^b, x symbolic, a==-0.9, b==2.5 wrong" << endl;
+        clog << "returned: " << e5 << endl;
+        return 1;
+    }
+    
+    ex e6=e1.subs(lst(a==numeric(3)+numeric(5.3)*I,b==-5));
+    if (!(is_ex_exactly_of_type(e6,power) &&
+          is_ex_exactly_of_type(e6.op(0),symbol) &&
+          is_ex_exactly_of_type(e6.op(1),numeric) &&
+          e6.is_equal(power(x,numeric(-15)+numeric(5.3)*numeric(-5)*I)) )) {
+        clog << "(x^a)^b, x symbolic, a==3+5.3*I, b==-5 wrong" << endl;
+        clog << "returned: " << e6 << endl;
+        return 1;
+    }
+    return 0;
+}
+
+static unsigned powerlaws2(void)
+{
+    // (a*x)^b = a^b * x^b
+    
+    symbol x("x");
+    symbol a("a");
+    symbol b("b");
+    
+    ex e1=power(a*x,b);
+    if (!(is_ex_exactly_of_type(e1,power) &&
+          is_ex_exactly_of_type(e1.op(0),mul) &&
+          (e1.op(0).nops()==2) &&
+          is_ex_exactly_of_type(e1.op(0).op(0),symbol) &&
+          is_ex_exactly_of_type(e1.op(0).op(1),symbol) &&
+          is_ex_exactly_of_type(e1.op(1),symbol) &&
+          e1.is_equal(power(a*x,b)) )) {
+        clog << "(a*x)^b, x,a,b symbolic wrong" << endl;
+        clog << "returned: " << e1 << endl;
+        return 1;
+    }
+    
+    ex e2=e1.subs(a==3);
+    if (!(is_ex_exactly_of_type(e2,power) &&
+          is_ex_exactly_of_type(e2.op(0),mul) &&
+          (e2.op(0).nops()==2) &&
+          is_ex_exactly_of_type(e2.op(0).op(0),symbol) &&
+          is_ex_exactly_of_type(e2.op(0).op(1),numeric) &&
+          is_ex_exactly_of_type(e2.op(1),symbol) &&
+          e2.is_equal(power(3*x,b)) )) {
+        clog << "(a*x)^b, x,b symbolic, a==3 wrong" << endl;
+        clog << "returned: " << e2 << endl;
+        return 1;
+    }
+    
+    ex e3=e1.subs(b==-3);
+    if (!(is_ex_exactly_of_type(e3,mul) &&
+          (e3.nops()==2) &&
+          is_ex_exactly_of_type(e3.op(0),power) &&
+          is_ex_exactly_of_type(e3.op(1),power) &&
+          e3.is_equal(power(a,-3)*power(x,-3)) )) {
+        clog << "(a*x)^b, x,a symbolic, b==-3 wrong" << endl;
+        clog << "returned: " << e3 << endl;
+        return 1;
+    }
+    
+    ex e4=e1.subs(b==4.5);
+    if (!(is_ex_exactly_of_type(e4,power) &&
+          is_ex_exactly_of_type(e4.op(0),mul) &&
+          (e4.op(0).nops()==2) &&
+          is_ex_exactly_of_type(e4.op(0).op(0),symbol) &&
+          is_ex_exactly_of_type(e4.op(0).op(1),symbol) &&
+          is_ex_exactly_of_type(e4.op(1),numeric) &&
+          e4.is_equal(power(a*x,4.5)) )) {
+        clog << "(a*x)^b, x,a symbolic, b==4.5 wrong" << endl;
+        clog << "returned: " << e4 << endl;
+        return 1;
+    }
+    
+    ex e5=e1.subs(lst(a==3.2,b==3+numeric(5)*I));
+    if (!(is_ex_exactly_of_type(e5,mul) &&
+          (e5.nops()==2) &&
+          is_ex_exactly_of_type(e5.op(0),power) &&
+          is_ex_exactly_of_type(e5.op(1),numeric) &&
+          e5.is_equal(power(x,3+numeric(5)*I)*
+                      power(numeric(3.2),3+numeric(5)*I)) )) {
+        clog << "(a*x)^b, x symbolic, a==3.2, b==3+5*I wrong" << endl;
+        clog << "returned: " << e5 << endl;
+        return 1;
+    }
+    
+    ex e6=e1.subs(lst(a==-3.2,b==3+numeric(5)*I));
+    if (!(is_ex_exactly_of_type(e6,mul) &&
+          (e6.nops()==2) &&
+          is_ex_exactly_of_type(e6.op(0),power) &&
+          is_ex_exactly_of_type(e6.op(1),numeric) &&
+          e6.is_equal(power(-x,3+numeric(5)*I)*
+                      power(numeric(3.2),3+numeric(5)*I)) )) {
+        clog << "(a*x)^b, x symbolic, a==-3.2, b==3+5*I wrong" << endl;
+        clog << "returned: " << e6 << endl;
+        return 1;
+    }
+    
+    ex e7=e1.subs(lst(a==3+numeric(5)*I,b==3.2));
+    if (!(is_ex_exactly_of_type(e7,power) &&
+          is_ex_exactly_of_type(e7.op(0),mul) &&
+          (e7.op(0).nops()==2) &&
+          is_ex_exactly_of_type(e7.op(0).op(0),symbol) &&
+          is_ex_exactly_of_type(e7.op(0).op(1),numeric) &&
+          is_ex_exactly_of_type(e7.op(1),numeric) &&
+          e7.is_equal(power((3+numeric(5)*I)*x,3.2)) )) {
+        clog << "(a*x)^b, x symbolic, a==3+5*I, b==3.2 wrong" << endl;
+        clog << "returned: " << e7 << endl;
+        return 1;
+    }
+    
+    return 0;
+}
+
+static unsigned powerlaws3(void)
+{
+    // numeric evaluation
+
+    ex e1=power(numeric(4),numeric(1)/numeric(2));
+    if (e1 != 2) {
+        clog << "4^(1/2) wrongly returned " << e1 << endl;
+        return 1;
+    }
+    
+    ex e2=power(numeric(27),numeric(2)/numeric(3));
+    if (e2 != 9) {
+        clog << "27^(2/3) wrongly returned " << e2 << endl;
+        return 1;
+    }
+
+    ex e3=power(numeric(5),numeric(1)/numeric(2));
+    if (!(is_ex_exactly_of_type(e3,power) &&
+          e3.op(0).is_equal(numeric(5)) &&
+          e3.op(1).is_equal(numeric(1)/numeric(2)) )) {
+        clog << "5^(1/2) wrongly returned " << e3 << endl;
+        return 1;
+    }
+    
+    ex e4=power(numeric(5),evalf(numeric(1)/numeric(2)));
+    if (!(is_ex_exactly_of_type(e4,numeric))) {
+        clog << "5^(0.5) wrongly returned " << e4 << endl;
+        return 1;
+    }
+    
+    ex e5=power(evalf(numeric(5)),numeric(1)/numeric(2));
+    if (!(is_ex_exactly_of_type(e5,numeric))) {
+        clog << "5.0^(1/2) wrongly returned " << e5 << endl;
+        return 1;
+    }
+    
+    return 0;
+}
+
+static unsigned powerlaws4(void)
+{
+    // test for mul::eval()
+
+    symbol a("a");
+    symbol b("b");
+    symbol c("c");
+    
+    ex f1=power(a*b,ex(1)/ex(2));
+    ex f2=power(a*b,ex(3)/ex(2));
+    ex f3=c;
+
+    exvector v;
+    v.push_back(f1);
+    v.push_back(f2);
+    v.push_back(f3);
+    ex e1=mul(v);
+    if (e1!=a*a*b*b*c) {
+        clog << "(a*b)^(1/2)*(a*b)^(3/2)*c wrongly returned " << e1 << endl;
+        return 1;
+    }
+    return 0;
+}
+
+unsigned powerlaws(void)
+{
+    unsigned result = 0;
+    
+    cout << "checking power laws..." << flush;
+    clog << "---------power laws:" << endl;
+    
+    result += powerlaws1();
+    result += powerlaws2();
+    result += powerlaws3();
+    result += powerlaws4();
+    
+    if (!result) {
+        cout << " passed ";
+        clog << "(no output)" << endl;
+    } else {
+        cout << " failed ";
+    }
+    return result;
+}
diff --git a/check/result.ref b/check/result.ref
new file mode 100644 (file)
index 0000000..a328058
--- /dev/null
@@ -0,0 +1,28 @@
+---------several ex-bugs just out of pure paranoia:
+(no output)
+---------output of numeric types:
+Using 200 digits
+Pi evalfs to: 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644L0
+Catalan evalfs to: 0.9159655941772190150546035149323841107741493742816721342664981196217630197762547694793565129261151062485744226191961995790358988033258590594315947374811584069953320287733194605190387274781640878659090247L0
+EulerGamma evalfs to: 0.577215664901532860606512090082402431042159335939923598805767234884867726777664670936947063291746749514631447249807082480960504014486542836224173997644923536253500333742937337737673942792595258247094916L0
+Complex integers: {(0,0)=0} {(1,0)=1} {(1,1)=1+I} {(0,1)=I} {(-1,1)=-1+I} {(-1,0)=-1} {(-1,-1)=-1-I} {(0,-1)=-I} {(1,-1)=1-I} 
+---------consistency of numeric types:
+(no output)
+---------power laws:
+(no output)
+---------commutative expansion and substitution:
+(no output)
+---------consistency of symbolic functions:
+(no output)
+---------symbolic differentiation:
+(no output)
+---------polynomial GCD computation:
+(no output)
+---------rational function normalization:
+(no output)
+---------symbolic matrix manipulations:
+(no output)
+---------linear solve:
+(no output)
+---------series expansion:
+(no output)
diff --git a/check/series_expansion.cpp b/check/series_expansion.cpp
new file mode 100644 (file)
index 0000000..ceb9016
--- /dev/null
@@ -0,0 +1,130 @@
+// check/series_expansion.cpp
+
+/* Series expansion test (Laurent and Taylor series). */
+
+#include "ginac.h"
+
+static symbol x("x");
+
+static unsigned check_series(const ex &e, const ex &point, const ex &d)
+{
+       ex es = e.series(x, point, 8);
+       ex ep = static_cast<series *>(es.bp)->convert_to_poly();
+       if ((ep - d).compare(exZERO()) != 0) {
+               clog << "series expansion of " << e << " at " << point
+             << " erroneously returned " << ep << " (instead of " << d
+             << ")" << endl;
+               (ep-d).printtree(clog);
+               return 1;
+       }
+       return 0;
+}
+
+// Series expansion
+static unsigned series1(void)
+{
+       unsigned result = 0;
+       ex e, d;
+
+       e = sin(x);
+       d = x - pow(x, 3) / 6 + pow(x, 5) / 120 - pow(x, 7) / 5040 + Order(pow(x, 8));
+       result += check_series(e, exZERO(), d);
+
+       e = cos(x);
+       d = 1 - pow(x, 2) / 2 + pow(x, 4) / 24 - pow(x, 6) / 720 + Order(pow(x, 8));
+       result += check_series(e, exZERO(), d);
+
+       e = exp(x);
+       d = 1 + x + pow(x, 2) / 2 + pow(x, 3) / 6 + pow(x, 4) / 24 + pow(x, 5) / 120 + pow(x, 6) / 720 + pow(x, 7) / 5040 + Order(pow(x, 8));
+       result += check_series(e, exZERO(), d);
+
+       e = pow(1 - x, -1);
+       d = 1 + x + pow(x, 2) + pow(x, 3) + pow(x, 4) + pow(x, 5) + pow(x, 6) + pow(x, 7) + Order(pow(x, 8));
+       result += check_series(e, exZERO(), d);
+
+       e = x + pow(x, -1);
+       d = x + pow(x, -1);
+       result += check_series(e, exZERO(), d);
+
+       e = x + pow(x, -1);
+       d = 2 + pow(x-1, 2) - pow(x-1, 3) + pow(x-1, 4) - pow(x-1, 5) + pow(x-1, 6) - pow(x-1, 7) + Order(pow(x-1, 8));
+       result += check_series(e, exONE(), d);
+
+       e = pow(x + pow(x, 3), -1);
+       d = pow(x, -1) - x + pow(x, 3) - pow(x, 5) + Order(pow(x, 7));
+       result += check_series(e, exZERO(), d);
+
+       e = pow(pow(x, 2) + pow(x, 4), -1);
+       d = pow(x, -2) - 1 + pow(x, 2) - pow(x, 4) + Order(pow(x, 6));
+       result += check_series(e, exZERO(), d);
+
+       e = pow(sin(x), -2);
+       d = pow(x, -2) + numeric(1,3) + pow(x, 2) / 15 + pow(x, 4) * 2/189 + Order(pow(x, 5));
+       result += check_series(e, exZERO(), d);
+
+       e = sin(x) / cos(x);
+       d = x + pow(x, 3) / 3 + pow(x, 5) * 2/15 + pow(x, 7) * 17/315 + Order(pow(x, 8));
+       result += check_series(e, exZERO(), d);
+
+       e = cos(x) / sin(x);
+       d = pow(x, -1) - x / 3 - pow(x, 3) / 45 - pow(x, 5) * 2/945 + Order(pow(x, 6));
+       result += check_series(e, exZERO(), d);
+
+       e = pow(numeric(2), x);
+       ex t = log(ex(2)) * x;
+       d = 1 + t + pow(t, 2) / 2 + pow(t, 3) / 6 + pow(t, 4) / 24 + pow(t, 5) / 120 + pow(t, 6) / 720 + pow(t, 7) / 5040 + Order(pow(x, 8));
+       result += check_series(e, exZERO(), d.expand());
+
+       e = pow(Pi, x);
+       t = log(Pi) * x;
+       d = 1 + t + pow(t, 2) / 2 + pow(t, 3) / 6 + pow(t, 4) / 24 + pow(t, 5) / 120 + pow(t, 6) / 720 + pow(t, 7) / 5040 + Order(pow(x, 8));
+       result += check_series(e, exZERO(), d.expand());
+
+       return result;
+}
+
+// Series addition
+static unsigned series2(void)
+{
+       unsigned result = 0;
+       ex e, d;
+
+       e = pow(sin(x), -1).series(x, exZERO(), 8) + pow(sin(-x), -1).series(x, exZERO(), 12);
+       d = Order(pow(x, 6));
+       result += check_series(e, exZERO(), d);
+
+       return result;
+}
+
+// Series multiplication
+static unsigned series3(void)
+{
+       unsigned result = 0;
+       ex e, d;
+
+       e = sin(x).series(x, exZERO(), 8) * pow(sin(x), -1).series(x, exZERO(), 12);
+       d = 1 + Order(pow(x, 7));
+       result += check_series(e, exZERO(), d);
+
+       return result;
+}
+
+unsigned series_expansion(void)
+{
+       unsigned result = 0;
+
+       cout << "checking series expansion..." << flush;
+       clog << "---------series expansion:" << endl;
+
+       result += series1();
+       result += series2();
+       result += series3();
+
+       if (!result) {
+               cout << " passed ";
+               clog << "(no output)" << endl;
+       } else {
+               cout << " failed ";
+       }
+       return result;
+}
diff --git a/config.h.in b/config.h.in
new file mode 100644 (file)
index 0000000..a60a0fc
--- /dev/null
@@ -0,0 +1,58 @@
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define if lex declares yytext as a char * by default, not a char[].  */
+#undef YYTEXT_POINTER
+
+/* Define if you have the strdup function.  */
+#undef HAVE_STRDUP
+
+/* Define if you have the <CLN/cln.h> header file.  */
+#undef HAVE_CLN_CLN_H
+
+/* Define if you have the <algorithm> header file.  */
+#undef HAVE_ALGORITHM
+
+/* Define if you have the <iostream> header file.  */
+#undef HAVE_IOSTREAM
+
+/* Define if you have the <iterator> header file.  */
+#undef HAVE_ITERATOR
+
+/* Define if you have the <list> header file.  */
+#undef HAVE_LIST
+
+/* Define if you have the <map> header file.  */
+#undef HAVE_MAP
+
+/* Define if you have the <readline/history.h> header file.  */
+#undef HAVE_READLINE_HISTORY_H
+
+/* Define if you have the <readline/readline.h> header file.  */
+#undef HAVE_READLINE_READLINE_H
+
+/* Define if you have the <stdexcept> header file.  */
+#undef HAVE_STDEXCEPT
+
+/* Define if you have the <string> header file.  */
+#undef HAVE_STRING
+
+/* Define if you have the <strstream> header file.  */
+#undef HAVE_STRSTREAM
+
+/* Define if you have the <typeinfo> header file.  */
+#undef HAVE_TYPEINFO
+
+/* Define if you have the <unistd.h> header file.  */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the <vector> header file.  */
+#undef HAVE_VECTOR
+
+/* Define if you have the readline library (-lreadline).  */
+#undef HAVE_LIBREADLINE
+
+/* Define if you have the stdc++ library (-lstdc++).  */
+#undef HAVE_LIBSTDC__
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..2424819
--- /dev/null
+++ b/configure
@@ -0,0 +1,2337 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13 
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+  --enable-shared         build shared libraries [default=no]
+                          (a static library will still be built as well)"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  case "$ac_option" in
+  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) ac_optarg= ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case "$ac_option" in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir="$ac_optarg" ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build="$ac_optarg" ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file="$ac_optarg" ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir="$ac_optarg" ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    eval "enable_${ac_feature}=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix="$ac_optarg" ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he)
+    # Omit some internal or obsolete options to make the list less imposing.
+    # This message is too long to be a string in the A/UX 3.1 sh.
+    cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+  --cache-file=FILE       cache test results in FILE
+  --help                  print this message
+  --no-create             do not create output files
+  --quiet, --silent       do not print \`checking...' messages
+  --version               print the version of autoconf that created configure
+Directory and file names:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [same as prefix]
+  --bindir=DIR            user executables in DIR [EPREFIX/bin]
+  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
+  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
+  --datadir=DIR           read-only architecture-independent data in DIR
+                          [PREFIX/share]
+  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
+                          [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
+  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
+  --includedir=DIR        C header files in DIR [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
+  --infodir=DIR           info documentation in DIR [PREFIX/info]
+  --mandir=DIR            man documentation in DIR [PREFIX/man]
+  --srcdir=DIR            find the sources in DIR [configure dir or ..]
+  --program-prefix=PREFIX prepend PREFIX to installed program names
+  --program-suffix=SUFFIX append SUFFIX to installed program names
+  --program-transform-name=PROGRAM
+                          run sed PROGRAM on installed program names
+EOF
+    cat << EOF
+Host type:
+  --build=BUILD           configure for building on BUILD [BUILD=HOST]
+  --host=HOST             configure for HOST [guessed]
+  --target=TARGET         configure for TARGET [TARGET=HOST]
+Features and packages:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --x-includes=DIR        X include files are in DIR
+  --x-libraries=DIR       X library files are in DIR
+EOF
+    if test -n "$ac_help"; then
+      echo "--enable and --with options recognized:$ac_help"
+    fi
+    exit 0 ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host="$ac_optarg" ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir="$ac_optarg" ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir="$ac_optarg" ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir="$ac_optarg" ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir="$ac_optarg" ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir="$ac_optarg" ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir="$ac_optarg" ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir="$ac_optarg" ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix="$ac_optarg" ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix="$ac_optarg" ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix="$ac_optarg" ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name="$ac_optarg" ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir="$ac_optarg" ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir="$ac_optarg" ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site="$ac_optarg" ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir="$ac_optarg" ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir="$ac_optarg" ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target="$ac_optarg" ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers)
+    echo "configure generated by autoconf version 2.13"
+    exit 0 ;;
+
+  -with-* | --with-*)
+    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_${ac_package}='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    eval "with_${ac_package}=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes="$ac_optarg" ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries="$ac_optarg" ;;
+
+  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+    ;;
+
+  *)
+    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+      echo "configure: warning: $ac_option: invalid host type" 1>&2
+    fi
+    if test "x$nonopt" != xNONE; then
+      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+    fi
+    nonopt="$ac_option"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+  case "$ac_arg" in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=include/ginac.h
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_prog=$0
+  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+  else
+    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+  fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    echo "loading site script $ac_site_file"
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='       '
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+GiNaC_Major_Version=0
+GiNaC_Minor_Version=0
+GiNaC_Micro_Version=30
+GiNaC_Version="${GiNaC_Major_Version}.${GiNaC_Minor_Version}.${GiNaC_Micro_Version}"
+LibGiNaC_Ver="${GiNaC_Major_Version}:${GiNaC_Micro_Version}:${GiNaC_Minor_Version}"
+
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+  enableval="$enable_shared"
+  shared=${enableval}
+else
+  shared="no"
+fi
+
+
+for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:550: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CXX="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CXX="$ac_cv_prog_CXX"
+if test -n "$CXX"; then
+  echo "$ac_t""$CXX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$CXX" && break
+done
+test -n "$CXX" || CXX="gcc"
+
+
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:582: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 593 "configure"
+#include "confdefs.h"
+
+int main(){return(0);}
+EOF
+if { (eval echo configure:598: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  ac_cv_prog_cxx_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cxx_cross=no
+  else
+    ac_cv_prog_cxx_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cxx_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6
+if test $ac_cv_prog_cxx_works = no; then
+  { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:624: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
+echo "configure:629: checking whether we are using GNU C++" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.C <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:638: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gxx=yes
+else
+  ac_cv_prog_gxx=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gxx" 1>&6
+
+if test $ac_cv_prog_gxx = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+
+ac_test_CXXFLAGS="${CXXFLAGS+set}"
+ac_save_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS=
+echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
+echo "configure:657: checking whether ${CXX-g++} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.cc
+if test -z "`${CXX-g++} -g -c conftest.cc 2>&1`"; then
+  ac_cv_prog_cxx_g=yes
+else
+  ac_cv_prog_cxx_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cxx_g" 1>&6
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS="$ac_save_CXXFLAGS"
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+
+echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6
+echo "configure:689: checking how to run the C++ preprocessor" >&5
+if test -z "$CXXCPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+  CXXCPP="${CXX-g++} -E"
+  cat > conftest.$ac_ext <<EOF
+#line 702 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:707: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CXXCPP=/lib/cpp
+fi
+rm -f conftest*
+  ac_cv_prog_CXXCPP="$CXXCPP"
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+fi
+fi
+CXXCPP="$ac_cv_prog_CXXCPP"
+echo "$ac_t""$CXXCPP" 1>&6
+
+ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+echo $ac_n "checking for cout in -lstdc++""... $ac_c" 1>&6
+echo "configure:739: checking for cout in -lstdc++" >&5
+ac_lib_var=`echo stdc++'_'cout | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lstdc++  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 747 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char cout();
+
+int main() {
+cout()
+; return 0; }
+EOF
+if { (eval echo configure:761: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo stdc++ | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lstdc++ $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+for ac_hdr in iostream vector map string list typeinfo iterator strstream stdexcept algorithm
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:792: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 797 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:802: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+{ echo "configure: error: need to have ANSI compliant headers" 1>&2; exit 1; }
+fi
+done
+
+
+    for ac_hdr in CLN/cln.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:834: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 839 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:844: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+for ac_hdr in cln.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:871: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 876 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:881: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+{ echo "configure: error: cannot find header for Bruno Haible's CLN" 1>&2; exit 1; };
+        
+fi
+done
+
+    
+fi
+done
+
+
+
+    echo $ac_n "checking how to link with libcln""... $ac_c" 1>&6
+echo "configure:916: checking how to link with libcln" >&5
+    saved_LIBS="${LIBS}"
+    if eval "test \"`echo '$''{'ginac_cv_lib_cln_link'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  LIBS="-lcln"
+        case "${ac_cv_header_CLN_cln_h}" in
+        "yes")
+            cat > conftest.$ac_ext <<EOF
+#line 925 "configure"
+#include "confdefs.h"
+#include <CLN/cln.h>
+int main() {
+factorial(1);
+; return 0; }
+EOF
+if { (eval echo configure:932: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ginac_cv_lib_cln_link="-lcln"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ginac_cv_lib_cln_link="fail"
+fi
+rm -f conftest*
+            ;;
+        *)
+            cat > conftest.$ac_ext <<EOF
+#line 945 "configure"
+#include "confdefs.h"
+#include <cln.h>
+int main() {
+factorial(1);
+; return 0; }
+EOF
+if { (eval echo configure:952: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ginac_cv_lib_cln_link="-lcln"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ginac_cv_lib_cln_link="fail"
+fi
+rm -f conftest*
+            ;;
+        esac
+    
+fi
+
+    case "${ginac_cv_lib_cln_link}" in
+    "-lcln")
+        LIBS="-lcln ${saved_LIBS}"
+        echo "$ac_t""-lcln" 1>&6
+        
+    echo $ac_n "checking whether libcln behaves sane""... $ac_c" 1>&6
+echo "configure:973: checking whether libcln behaves sane" >&5
+    if eval "test \"`echo '$''{'ginac_cv_lib_cln_integrity'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  
+        case "${ac_cv_header_CLN_cln_h}" in
+        "yes")
+            if test "$cross_compiling" = yes; then
+  ginac_cv_lib_cln_integrity="guessing sane"
+else
+  cat > conftest.$ac_ext <<EOF
+#line 984 "configure"
+#include "confdefs.h"
+#ifdef __cplusplus
+extern "C" void exit(int);
+#endif
+#include <CLN/cln.h>
+int main() {
+cl_RA q(3); q = q/2; cl_RA p(3); p = p/2;
+if (q+p != 3) return 1; else return 0;
+}
+EOF
+if { (eval echo configure:995: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ginac_cv_lib_cln_integrity="sane"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ginac_cv_lib_cln_integrity="insane"
+fi
+rm -fr conftest*
+fi
+
+            ;;
+        *)
+            if test "$cross_compiling" = yes; then
+  ginac_cv_lib_cln_integrity="guessing sane"
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1013 "configure"
+#include "confdefs.h"
+#ifdef __cplusplus
+extern "C" void exit(int);
+#endif
+#include <cln.h>
+int main() {
+cl_RA q(3); q = q/2; cl_RA p(3); p = p/2;
+if (q+p != 3) return 1; else return 0;
+}
+EOF
+if { (eval echo configure:1024: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ginac_cv_lib_cln_integrity="sane"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ginac_cv_lib_cln_integrity="insane"
+fi
+rm -fr conftest*
+fi
+
+            ;;
+        esac
+    
+fi
+
+    case "${ginac_cv_lib_cln_integrity}" in
+    "sane")
+        echo "$ac_t""yes" 1>&6
+    ;;
+    "insane")
+        echo "$ac_t""no" 1>&6
+        echo "configure: warning: maybe version of libcln is older than 1.0.2?" 1>&2
+    ;;
+    "guessing sane")
+        echo "$ac_t""hopefully" 1>&6
+    ;;
+    *)
+        echo "configure: warning: you found a bug in the configure script!" 1>&2
+    ;;
+    esac
+
+    ;;
+    "fail")
+        LIBS="${saved_LIBS}"
+        echo "$ac_t""" 1>&6
+        echo "configure: warning: linking with libcln failed" 1>&2
+    ;;
+    *)
+        LIBS="${saved_LIBS}"
+    ;;
+    esac
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:1099: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS=":"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+         if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         else
+           ac_cv_path_install="$ac_dir/$ac_prog -c"
+           break 2
+         fi
+       fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL="$ac_cv_path_install"
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL="$ac_install_sh"
+  fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+# Extract the first word of "makedepend", so it can be a program name with args.
+set dummy makedepend; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1154: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_MAKEDEPEND'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$MAKEDEPEND" in
+  /*)
+  ac_cv_path_MAKEDEPEND="$MAKEDEPEND" # Let the user override the test with a path.
+  ;;
+  ?:/*)                         
+  ac_cv_path_MAKEDEPEND="$MAKEDEPEND" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_MAKEDEPEND="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_MAKEDEPEND" && ac_cv_path_MAKEDEPEND=""""
+  ;;
+esac
+fi
+MAKEDEPEND="$ac_cv_path_MAKEDEPEND"
+if test -n "$MAKEDEPEND"; then
+  echo "$ac_t""$MAKEDEPEND" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+case "${shared}" in
+"yes"|"Yes"|"YES")      # Default-enable ("yes") or user was nitpicking:
+    shared="shlib";
+    # Extract the first word of "libtool", so it can be a program name with args.
+set dummy libtool; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1193: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_LIBTOOL'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$LIBTOOL" in
+  /*)
+  ac_cv_path_LIBTOOL="$LIBTOOL" # Let the user override the test with a path.
+  ;;
+  ?:/*)                         
+  ac_cv_path_LIBTOOL="$LIBTOOL" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_LIBTOOL="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_LIBTOOL" && ac_cv_path_LIBTOOL=""""
+  ;;
+esac
+fi
+LIBTOOL="$ac_cv_path_LIBTOOL"
+if test -n "$LIBTOOL"; then
+  echo "$ac_t""$LIBTOOL" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+    if test "${LIBTOOL}" == ""; then
+        echo "configure: warning: libtool not found: building static lib only" 1>&2
+        shared="";
+    fi
+    ;;
+*)      # Default, default-disable ("no") or user entered bogus:
+    shared="";
+    ;;
+esac
+# Extract the first word of "flex", so it can be a program name with args.
+set dummy flex; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1238: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$LEX"; then
+  ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_LEX="flex"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_LEX" && ac_cv_prog_LEX="lex"
+fi
+fi
+LEX="$ac_cv_prog_LEX"
+if test -n "$LEX"; then
+  echo "$ac_t""$LEX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$LEXLIB"
+then
+  case "$LEX" in
+  flex*) ac_lib=fl ;;
+  *) ac_lib=l ;;
+  esac
+  echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6
+echo "configure:1272: checking for yywrap in -l$ac_lib" >&5
+ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-l$ac_lib  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1280 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char yywrap();
+
+int main() {
+yywrap()
+; return 0; }
+EOF
+if { (eval echo configure:1294: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LEXLIB="-l$ac_lib"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+for ac_prog in 'bison -y' byacc
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1321: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_YACC="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+YACC="$ac_cv_prog_YACC"
+if test -n "$YACC"; then
+  echo "$ac_t""$YACC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+echo $ac_n "checking lex output file root""... $ac_c" 1>&6
+echo "configure:1352: checking lex output file root" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_lex_root'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  # The minimal lex program is just a single line: %%.  But some broken lexes
+# (Solaris, I think it was) want two %% lines, so accommodate them.
+echo '%%
+%%' | $LEX
+if test -f lex.yy.c; then
+  ac_cv_prog_lex_root=lex.yy
+elif test -f lexyy.c; then
+  ac_cv_prog_lex_root=lexyy
+else
+  { echo "configure: error: cannot find output from $LEX; giving up" 1>&2; exit 1; }
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_lex_root" 1>&6
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+echo $ac_n "checking whether yytext is a pointer""... $ac_c" 1>&6
+echo "configure:1373: checking whether yytext is a pointer" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_lex_yytext_pointer'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  # POSIX says lex can declare yytext either as a pointer or an array; the
+# default is implementation-dependent. Figure out which it is, since
+# not all implementations provide the %pointer and %array declarations.
+ac_cv_prog_lex_yytext_pointer=no
+echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c
+ac_save_LIBS="$LIBS"
+LIBS="$LIBS $LEXLIB"
+cat > conftest.$ac_ext <<EOF
+#line 1385 "configure"
+#include "confdefs.h"
+`cat $LEX_OUTPUT_ROOT.c`
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1392: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ac_cv_prog_lex_yytext_pointer=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+rm -f "${LEX_OUTPUT_ROOT}.c"
+
+fi
+
+echo "$ac_t""$ac_cv_prog_lex_yytext_pointer" 1>&6
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+  cat >> confdefs.h <<\EOF
+#define YYTEXT_POINTER 1
+EOF
+
+fi
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1414: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1419 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1427: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  ac_cv_header_stdc=yes
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1444 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "memchr" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1462 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "free" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+  :
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1483 "configure"
+#include "confdefs.h"
+#ifdef __cplusplus
+extern "C" void exit(int);
+#endif
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1497: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  :
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+  cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+for ac_hdr in unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1524: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1529 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1534: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in strdup
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1563: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1568 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1594: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_hdr in readline/readline.h readline/history.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1622: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1627 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1632: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+{ echo "configure: error: need to have GNU readline headers" 1>&2; exit 1; }
+fi
+done
+
+echo $ac_n "checking for readline in -lreadline""... $ac_c" 1>&6
+echo "configure:1660: checking for readline in -lreadline" >&5
+ac_lib_var=`echo readline'_'readline | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lreadline  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1668 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char readline();
+
+int main() {
+readline()
+; return 0; }
+EOF
+if { (eval echo configure:1682: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo readline | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lreadline $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+{ echo "configure: error: need to have GNU readline library" 1>&2; exit 1; }
+fi
+
+# 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:1713: 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
+  case "$DOXYGEN" in
+  /*)
+  ac_cv_path_DOXYGEN="$DOXYGEN" # Let the user override the test with a path.
+  ;;
+  ?:/*)                         
+  ac_cv_path_DOXYGEN="$DOXYGEN" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_DOXYGEN="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_DOXYGEN" && ac_cv_path_DOXYGEN=""""
+  ;;
+esac
+fi
+DOXYGEN="$ac_cv_path_DOXYGEN"
+if test -n "$DOXYGEN"; then
+  echo "$ac_t""$DOXYGEN" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+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:1749: 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
+  case "$LATEX" in
+  /*)
+  ac_cv_path_LATEX="$LATEX" # Let the user override the test with a path.
+  ;;
+  ?:/*)                         
+  ac_cv_path_LATEX="$LATEX" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_LATEX="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_LATEX" && ac_cv_path_LATEX=""""
+  ;;
+esac
+fi
+LATEX="$ac_cv_path_LATEX"
+if test -n "$LATEX"; then
+  echo "$ac_t""$LATEX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+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:1785: 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
+  case "$MAKEINDEX" in
+  /*)
+  ac_cv_path_MAKEINDEX="$MAKEINDEX" # Let the user override the test with a path.
+  ;;
+  ?:/*)                         
+  ac_cv_path_MAKEINDEX="$MAKEINDEX" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_MAKEINDEX="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_MAKEINDEX" && ac_cv_path_MAKEINDEX=""""
+  ;;
+esac
+fi
+MAKEINDEX="$ac_cv_path_MAKEINDEX"
+if test -n "$MAKEINDEX"; then
+  echo "$ac_t""$MAKEINDEX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+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:1821: 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
+  case "$DVIPS" in
+  /*)
+  ac_cv_path_DVIPS="$DVIPS" # Let the user override the test with a path.
+  ;;
+  ?:/*)                         
+  ac_cv_path_DVIPS="$DVIPS" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_DVIPS="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_DVIPS" && ac_cv_path_DVIPS=""""
+  ;;
+esac
+fi
+DVIPS="$ac_cv_path_DVIPS"
+if test -n "$DVIPS"; then
+  echo "$ac_t""$DVIPS" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+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:1857: 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
+  case "$FIG2DEV" in
+  /*)
+  ac_cv_path_FIG2DEV="$FIG2DEV" # Let the user override the test with a path.
+  ;;
+  ?:/*)                         
+  ac_cv_path_FIG2DEV="$FIG2DEV" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_FIG2DEV="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_FIG2DEV" && ac_cv_path_FIG2DEV=""""
+  ;;
+esac
+fi
+FIG2DEV="$ac_cv_path_FIG2DEV"
+if test -n "$FIG2DEV"; then
+  echo "$ac_t""$FIG2DEV" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "jade", so it can be a program name with args.
+set dummy jade; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1893: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_JADE'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$JADE" in
+  /*)
+  ac_cv_path_JADE="$JADE" # Let the user override the test with a path.
+  ;;
+  ?:/*)                         
+  ac_cv_path_JADE="$JADE" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_JADE="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_JADE" && ac_cv_path_JADE=""""
+  ;;
+esac
+fi
+JADE="$ac_cv_path_JADE"
+if test -n "$JADE"; then
+  echo "$ac_t""$JADE" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+# Extract the first word of "jadetex", so it can be a program name with args.
+set dummy jadetex; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1929: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_JADETEX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  case "$JADETEX" in
+  /*)
+  ac_cv_path_JADETEX="$JADETEX" # Let the user override the test with a path.
+  ;;
+  ?:/*)                         
+  ac_cv_path_JADETEX="$JADETEX" # Let the user override the test with a dos path.
+  ;;
+  *)
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do 
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_path_JADETEX="$ac_dir/$ac_word"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_JADETEX" && ac_cv_path_JADETEX=""""
+  ;;
+esac
+fi
+JADETEX="$ac_cv_path_JADETEX"
+if test -n "$JADETEX"; then
+  echo "$ac_t""$JADETEX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[        ]*VPATH[        ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+  case "\$ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+    echo "$CONFIG_STATUS generated by autoconf version 2.13"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "\$ac_cs_usage"; exit 0 ;;
+  *) echo "\$ac_cs_usage"; exit 1 ;;
+  esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile src/Makefile check/Makefile ginsh/Makefile doc/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CXX@%$CXX%g
+s%@CXXCPP@%$CXXCPP%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@MAKEDEPEND@%$MAKEDEPEND%g
+s%@LIBTOOL@%$LIBTOOL%g
+s%@LEX@%$LEX%g
+s%@LEXLIB@%$LEXLIB%g
+s%@YACC@%$YACC%g
+s%@LEX_OUTPUT_ROOT@%$LEX_OUTPUT_ROOT%g
+s%@DOXYGEN@%$DOXYGEN%g
+s%@LATEX@%$LATEX%g
+s%@MAKEINDEX@%$MAKEINDEX%g
+s%@DVIPS@%$DVIPS%g
+s%@FIG2DEV@%$FIG2DEV%g
+s%@JADE@%$JADE%g
+s%@JADETEX@%$JADETEX%g
+s%@shared@%$shared%g
+s%@LibGiNaC_Ver@%$LibGiNaC_Ver%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile src/Makefile check/Makefile ginsh/Makefile doc/Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    # The file is in a subdirectory.
+    test ! -d "$ac_dir" && mkdir "$ac_dir"
+    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case "$ac_given_srcdir" in
+  .)  srcdir=.
+      if test -z "$ac_dots"; then top_srcdir=.
+      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+  *) # Relative path.
+    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+  case "$ac_given_INSTALL" in
+  [/$]*) INSTALL="$ac_given_INSTALL" ;;
+  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+  esac
+
+  echo creating "$ac_file"
+  rm -f "$ac_file"
+  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+  case "$ac_file" in
+  *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+  *) ac_comsub= ;;
+  esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([  ]*\)#\([        ]*define[       ][      ]*\)'
+ac_dB='\([     ][      ]*\)[^  ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='\([     ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+  CONFIG_HEADERS="config.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  echo creating $ac_file
+
+  rm -f conftest.frag conftest.in conftest.out
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h.  And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[   ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+  ac_lines=`grep -c . conftest.vals`
+  # grep -c gives empty output for an empty file on some AIX systems.
+  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+  # Write a limited-size here document to conftest.frag.
+  echo '  cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+  echo 'CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+  rm -f conftest.vals
+  mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+  rm -f conftest.frag conftest.h
+  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
+  cat conftest.in >> conftest.h
+  rm -f conftest.in
+  if cmp -s $ac_file conftest.h 2>/dev/null; then
+    echo "$ac_file is unchanged"
+    rm -f conftest.h
+  else
+    # Remove last slash and all that follows it.  Not all systems have dirname.
+      ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+      if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+      # The file is in a subdirectory.
+      test ! -d "$ac_dir" && mkdir "$ac_dir"
+    fi
+    rm -f $ac_file
+    mv conftest.h $ac_file
+  fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+echo "now type make"
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..06a7d98
--- /dev/null
@@ -0,0 +1,101 @@
+dnl ===========================================================================
+dnl Process this file with GNU Autoconf to produce a configure script. Then
+dnl call ./configure to create Makefiles. After that say make and make install.
+dnl See aclocal.m4 for additional self-made macros.
+dnl ===========================================================================
+
+dnl This file is used as a signal that everything is in place:
+AC_INIT(include/ginac.h)
+dnl A convenient header file for some additional system-dependend output:
+AC_CONFIG_HEADER(config.h)
+
+dnl Set the Version Number at this place only:
+GiNaC_Major_Version=0
+GiNaC_Minor_Version=0
+GiNaC_Micro_Version=30
+dnl This composite variable can be inserted where it appears necessary:
+GiNaC_Version="${GiNaC_Major_Version}.${GiNaC_Minor_Version}.${GiNaC_Micro_Version}"
+dnl This composition is needed for libtool, if a shared lib shall be built:
+LibGiNaC_Ver="${GiNaC_Major_Version}:${GiNaC_Micro_Version}:${GiNaC_Minor_Version}"
+
+dnl ===========================================================================
+dnl Several features need to be added to standard-configure:
+dnl ===========================================================================
+AC_ARG_ENABLE(shared,
+    [  --enable-shared         build shared libraries [default=no]
+                          (a static library will still be built as well)],
+    shared=${enableval}, shared="no")
+
+dnl ===========================================================================
+dnl Check for the compiler and all the utilities needed for the build:
+dnl ===========================================================================
+dnl Which is the C++ Compiler? (whether to use c++, g++, gcc, CC, cxx, cc++...)
+AC_PROG_CXX
+dnl How to run the C++ preprocessor?
+AC_PROG_CXXCPP
+dnl Switch to C++ language mode for the following libraries and headers:
+AC_LANG_CPLUSPLUS
+dnl Make sure the following libraries work by testing for symbols therein. 
+dnl They are automatically added the the variable $LIBS and thus passed into
+dnl the Makefile:
+AC_CHECK_LIB(stdc++, cout)
+dnl Make sure all the necessary new-style headers are installed on the system.
+dnl If one of them cannot be found the system is probably not ANSI-conform
+dnl enough so trying the .h-style headers is a waste of time.
+AC_CHECK_HEADERS(iostream vector map string list typeinfo iterator strstream stdexcept algorithm, ,
+    AC_MSG_ERROR(need to have ANSI compliant headers))
+dnl We need to have Bruno Haible's CLN installed (macros are in aclocal.m4):
+GINAC_CHECK_CLN_H
+GINAC_CHECK_LIBCLN
+dnl We need to distribure install-sh anyways since otherwise configure will
+dnl refuse to do several things, like divert into subdirs and so:
+AC_PROG_INSTALL
+dnl Todd Brunhoff's makedepend utility is needed by make:
+AC_PATH_PROG(MAKEDEPEND, makedepend, "")
+dnl We need GNU libtool if the user chose to create a shared lib. (By using a 
+dnl little trick we can safely recycle the variable shlib which is later passed
+dnl into the Makefile.)
+case "${shared}" in
+"yes"|"Yes"|"YES")      # Default-enable ("yes") or user was nitpicking:
+    shared="shlib";
+    AC_PATH_PROG(LIBTOOL, libtool, "")
+    if test "${LIBTOOL}" == ""; then
+        AC_MSG_WARN([libtool not found: building static lib only])
+        shared="";
+    fi
+    ;;
+*)      # Default, default-disable ("no") or user entered bogus:
+    shared="";
+    ;;
+esac
+dnl Check for helpers needed for building the GiNaC interactive shell:
+AC_PROG_LEX
+AC_PROG_YACC
+AC_DECL_YYTEXT
+AC_HEADER_STDC
+AC_CHECK_HEADERS(unistd.h)
+AC_CHECK_FUNCS(strdup)
+AC_CHECK_HEADERS(readline/readline.h readline/history.h, , AC_MSG_ERROR(need to have GNU readline headers))
+AC_CHECK_LIB(readline, readline, , AC_MSG_ERROR(need to have GNU readline library))
+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:
+AC_PATH_PROG(DOXYGEN, doxygen, "")
+AC_PATH_PROG(LATEX, latex, "")
+AC_PATH_PROG(MAKEINDEX, makeindex, "")
+AC_PATH_PROG(DVIPS, dvips, "")
+AC_PATH_PROG(FIG2DEV, fig2dev, "")
+AC_PATH_PROG(JADE, jade, "")
+AC_PATH_PROG(JADETEX, jadetex, "")
+
+dnl ===========================================================================
+dnl Substitute these variables in the Makefile:
+dnl ===========================================================================
+AC_SUBST(shared)
+AC_SUBST(LibGiNaC_Ver)
+
+dnl ===========================================================================
+dnl Produce a Makefile from Makefile.in:
+dnl ===========================================================================
+AC_OUTPUT([Makefile src/Makefile check/Makefile ginsh/Makefile doc/Makefile])
+echo "now type make"
diff --git a/doc/DoxyfileHTML b/doc/DoxyfileHTML
new file mode 100644 (file)
index 0000000..fefa253
--- /dev/null
@@ -0,0 +1,371 @@
+# Doxyfile 0.49-990522
+# This file describes the settings to be used by doxygen for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of word surrounded
+# by quotes) that should identify the project. 
+
+PROJECT_NAME         = GiNaC
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER       =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY     = ./doc
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are: Dutch
+
+OUTPUT_LANGUAGE      = English
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS             = YES
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX        = NO
+
+# If the EXTRACT_ALL tag is set to YES all classes and functions will be
+# included in the documentation, even if no documentation was available.
+
+EXTRACT_ALL          = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE      = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members inside documented classes or files.
+
+HIDE_UNDOC_MEMBERS   = NO
+
+# If the HIDE_UNDOC_CLASSESS tag is set to YES, Doxygen will hide all
+# undocumented classes.
+
+HIDE_UNDOC_CLASSES   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC    = YES
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS        = NO
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF         = YES
+
+# If the FULL_PATH_NAMES tag is set to YES Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES      = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user defined part of the path. Stripping is
+# only done if the specified string matches the left-hand part of the path.
+
+STRIP_FROM_PATH      =
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a class diagram (in Html and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off.
+
+CLASS_DIAGRAMS       = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO (the default) then Doxygen
+# will only generate file names in lower case letters. If set to
+# YES upper case letters are also allowed. This is useful if you have
+# classes or files whose names only differ in case and if your file system
+# supports case sensitive file names.
+
+CASE_SENSE_NAMES     = YES
+
+# If the VERBATIM_HEADERS tag is set the YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS     = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                = ./
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+FILE_PATTERNS        = *.cpp *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE            = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE              =
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS     =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH         =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER         =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output
+
+GENERATE_HTML        = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT          = reference
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER          =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER          = ./doc/Doxyfooter.html
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS   = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX       = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT         = latex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX        = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE           = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES       =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN         = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT           =
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION        = .3
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor 
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed.
+
+MACRO_EXPANSION      = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES      = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH         = ./
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed.
+
+PREDEFINED           =
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED tag.
+
+EXPAND_ONLY_PREDEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references 
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tagfiles. 
+
+TAGFILES             =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE     =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS         = NO
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH            = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the search engine 
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE         = NO
+
+# The CGI_NAME tag should be the name of the CGI script that
+# starts the search engine (doxysearch) with the correct parameters.
+# A script with this name will be generated by doxygen.
+
+CGI_NAME             = search.cgi
+
+# The CGI_URL tag should be the absolute URL to the directory where the
+# cgi binaries are located. See the documentation of your http daemon for 
+# details.
+
+CGI_URL              =
+
+# The DOC_URL tag should be the absolute URL to the directory where the
+# documentation is located. If left blank the absolute path to the 
+# documentation, with file:// prepended to it, will be used.
+
+DOC_URL              =
+
+# The DOC_ABSPATH tag should be the absolute path to the directory where the
+# documentation is located. If left blank the directory on the local machine
+# will be used.
+
+DOC_ABSPATH          =
+
+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
+# is installed.
+
+BIN_ABSPATH          = /usr/local/bin/
+
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to 
+# documentation generated for other projects. This allows doxysearch to search
+# the documentation for these projects as well.
+
+EXT_DOC_PATHS        =
diff --git a/doc/DoxyfileTEX b/doc/DoxyfileTEX
new file mode 100644 (file)
index 0000000..670ca23
--- /dev/null
@@ -0,0 +1,371 @@
+# Doxyfile 0.49-990522
+# This file describes the settings to be used by doxygen for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of word surrounded
+# by quotes) that should identify the project. 
+
+PROJECT_NAME         = GiNaC
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER       =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY     = ./doc
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are: Dutch
+
+OUTPUT_LANGUAGE      = English
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS             = YES
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX        = NO
+
+# If the EXTRACT_ALL tag is set to YES all classes and functions will be
+# included in the documentation, even if no documentation was available.
+
+EXTRACT_ALL          = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE      = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members inside documented classes or files.
+
+HIDE_UNDOC_MEMBERS   = NO
+
+# If the HIDE_UNDOC_CLASSESS tag is set to YES, Doxygen will hide all
+# undocumented classes.
+
+HIDE_UNDOC_CLASSES   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC    = YES
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS        = NO
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF         = YES
+
+# If the FULL_PATH_NAMES tag is set to YES Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES      = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user defined part of the path. Stripping is
+# only done if the specified string matches the left-hand part of the path.
+
+STRIP_FROM_PATH      =
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a class diagram (in Html and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off.
+
+CLASS_DIAGRAMS       = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO (the default) then Doxygen
+# will only generate file names in lower case letters. If set to
+# YES upper case letters are also allowed. This is useful if you have
+# classes or files whose names only differ in case and if your file system
+# supports case sensitive file names.
+
+CASE_SENSE_NAMES     = YES
+
+# If the VERBATIM_HEADERS tag is set the YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS     = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                = ./
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+FILE_PATTERNS        = *.cpp *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE            = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE              =
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS     =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH         =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER         =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output
+
+GENERATE_HTML        = NO
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT          = reference
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER          =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER          = ./doc/Doxyfooter.html
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS   = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX       = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT         = latex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX        = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE           = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES       =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN         = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT           =
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION        = .3
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor 
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed.
+
+MACRO_EXPANSION      = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES      = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH         = ./
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed.
+
+PREDEFINED           =
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED tag.
+
+EXPAND_ONLY_PREDEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references 
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tagfiles. 
+
+TAGFILES             =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE     =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS         = NO
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH            = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the search engine 
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE         = NO
+
+# The CGI_NAME tag should be the name of the CGI script that
+# starts the search engine (doxysearch) with the correct parameters.
+# A script with this name will be generated by doxygen.
+
+CGI_NAME             = search.cgi
+
+# The CGI_URL tag should be the absolute URL to the directory where the
+# cgi binaries are located. See the documentation of your http daemon for 
+# details.
+
+CGI_URL              =
+
+# The DOC_URL tag should be the absolute URL to the directory where the
+# documentation is located. If left blank the absolute path to the 
+# documentation, with file:// prepended to it, will be used.
+
+DOC_URL              =
+
+# The DOC_ABSPATH tag should be the absolute path to the directory where the
+# documentation is located. If left blank the directory on the local machine
+# will be used.
+
+DOC_ABSPATH          =
+
+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
+# is installed.
+
+BIN_ABSPATH          = /usr/local/bin/
+
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to 
+# documentation generated for other projects. This allows doxysearch to search
+# the documentation for these projects as well.
+
+EXT_DOC_PATHS        =
diff --git a/doc/Doxyfooter.html b/doc/Doxyfooter.html
new file mode 100644 (file)
index 0000000..b63e6e6
--- /dev/null
@@ -0,0 +1,9 @@
+<hr>
+<small><i>This page is part of the <b><a
+href="http://wwwthep.physik.uni-mainz.de/GiNaC/">GiNaC</a></b>
+developer's reference. It was generated automatically by <a
+href="http://www.stack.nl/~dimitri/doxygen/index.html">doxygen</a>. For
+an introduction, see the <a href="../tutorial/index.html">tutorial</a>.</i></small>
+</body>
+</html>
+
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644 (file)
index 0000000..66acd0f
--- /dev/null
@@ -0,0 +1,169 @@
+# Generated automatically from Makefile.in by configure.
+# This is the prototype Makefile for all of GiNaC's documentation.  It tries to
+# be tolerant---if some tools were not found it skips the built of that part
+# of documentation and tries to continue.
+
+# Substitution variables from configure skript:
+# Here come the usual install directories in GNU-configure fashion:
+prefix = /usr/local
+docdir = ${prefix}/share/doc/GiNaC
+srcdir = .
+# Dimitri van Heesch's Doxygen is needed for developer's resource:
+DOXYGEN = /usr/local/bin_i386/doxygen
+# LaTeX and friends are needed for processing developer's resource for print:
+LATEX = /usr/local/bin/latex
+MAKEINDEX = /usr/local/bin/makeindex
+DVIPS = /usr/local/bin/dvips
+FIG2DEV = /usr/bin/X11/fig2dev
+# Jade and friends needed for generating the tutorial:
+JADE = /usr/bin/jade
+JADETEX = /usr/local/bin/jadetex
+# Arguments for Jade and friends (does anybody know how to find them out?)
+# JADEARGS_TEX = -t tex -o tutorial.tex -d /usr/lib/dsssl/stylesheets/docbook/print/docbook.dsl
+JADEARGS_TEX = -t tex -o tutorial.tex -d /usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/print/docbook.dsl
+# JADEARGS_HTML = -t sgml -d /usr/lib/dsssl/stylesheets/docbook/html/docbook.dsl
+JADEARGS_HTML = -t sgml -d /usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/html/docbook.dsl
+# Autoconf macro AC_PROC_INSTALL sets these:
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+# All LaTeX builds will take place in a separate subdirectory:
+VPATH = .:./latex:./tutorial
+
+# default target:
+all: reference tutorial
+
+# REFERENCE:
+# This section produces HTML'ed and TeX'ed developer's reference from the
+# sources with a JavaDoc-like tool (in this case doxygen):
+reference_html:
+       @ if [ ! -d ${srcdir}/reference ]; then mkdir ${srcdir}/reference; fi
+       @ if [ "${DOXYGEN}" ]; then \
+               echo "Running ${DOXYGEN} ./DoxyfileHTML..."; \
+               cd ..; ${DOXYGEN} ./doc/DoxyfileHTML; \
+       else \
+               echo "warning: target reference_html disabled by configuration"; \
+       fi
+
+reference.tex:
+       @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi
+       @ if [ "${DOXYGEN}" ]; then \
+               echo "Running ${DOXYGEN} ./DoxyfileTEX..."; \
+               cd ..; ${DOXYGEN} ./doc/DoxyfileTEX; \
+       else \
+               echo "warning: target reference.tex disabled by configuration"; \
+       fi
+       - mv ${srcdir}/latex/refman.tex ${srcdir}/latex/reference.tex 
+
+reference.dvi: reference.tex
+       @ if [ "${LATEX}" -a "${MAKEINDEX}" ]; then \
+               cd latex; \
+               ${LATEX} reference.tex && \
+               ${MAKEINDEX} reference.idx && \
+               ${LATEX} reference.tex; \
+       else \
+               echo "warning: target reference.dvi disabled by configuration"; \
+       fi
+
+reference.ps: reference.dvi
+       @ if [ "${DVIPS}" ]; then \
+               echo "Running ${DVIPS} -o reference.ps reference.dvi..."; \
+               cd latex; ${DVIPS} -o reference.ps reference.dvi; \
+       else \
+               echo "warning: target reference.ps disabled by configuration"; \
+       fi
+
+reference: reference_html reference.ps
+
+# TUTORIAL:
+# This section produces HTML'ed and TeX'ed versions of the tutorial using a
+# SGML to TeX converter (in this case jade).  As a dirty hack, we are doing
+# some regexpese to tutorial.sgml prior to parsing it, in order to allow for
+# different graphics output.  This seems to be an ugly limitation of docbook...
+
+EPS = classhierarchy.eps rep_naive.eps rep_pair.eps
+PNG = classhierarchy.png rep_naive.png rep_pair.png
+
+tutorial/index.html: tutorial.sgml.in ${PNG}
+       @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi
+       @ if [ "${JADE}" ]; then \
+               sed -e 's/graext/png/g' -e 's/GRAEXT/GIF/g' tutorial.sgml.in > tutorial.sgml; \
+               echo "Running ${JADE} ${JADEARGS_HTML} tutorial.sgml..."; \
+               cd tutorial/; ${JADE} ${JADEARGS_HTML} ../tutorial.sgml; \
+               if [ -f book1.html ]; then cp book1.html index.html; fi; \
+       else \
+               echo "warning: target tutorial_html disabled by configuration"; \
+       fi
+
+tutorial.tex: tutorial.sgml.in ${EPS}
+       @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi
+       @ if [ "${JADE}" -a "${LATEX}" ]; then \
+               sed -e 's/graext/eps/g' -e 's/GRAEXT/EPS/g' tutorial.sgml.in > tutorial.sgml; \
+               echo "Running ${JADE} ${JADEARGS_TEX} tutorial.sgml..."; \
+               cd latex; ${JADE} ${JADEARGS_TEX} ../tutorial.sgml ; \
+       else \
+               echo "warning: target tutorial.tex disabled by configuration"; \
+       fi
+
+tutorial.dvi: tutorial.tex
+       @ if [ "${JADETEX}" ]; then \
+               echo "Running ${JADETEX} tutorial.tex..."; \
+               cd latex; ${JADETEX} tutorial.tex && ${JADETEX} tutorial.tex && ${JADETEX} tutorial.tex; \
+       else \
+               echo "warning: target tutorial.dvi disabled by configuration"; \
+       fi
+
+tutorial.ps: tutorial.dvi
+       @ if [ "${DVIPS}" ]; then \
+               echo "Running ${DVIPS} tutorial.dvi -o tutorial.ps..."; \
+               cd latex; ${DVIPS} tutorial.dvi -o tutorial.ps; \
+       else \
+               echo "warning: target tutorial.ps disabled by configuration"; \
+       fi
+
+tutorial:      tutorial/index.html tutorial.ps
+
+# Target for installing all generated documentation files on the system.
+# (Foolproof: installs what we got, even if one or more targets failed.)
+install:
+       - ${INSTALL} -d ${docdir}/reference/
+       - ${INSTALL_DATA} ${srcdir}/reference/* ${docdir}/reference/
+       - ${INSTALL_DATA} ${srcdir}/latex/reference.ps ${docdir}/
+       - ${INSTALL} -d ${docdir}/tutorial/
+       - ${INSTALL_DATA} ${srcdir}/tutorial/* ${docdir}/tutorial/
+       - ${INSTALL_DATA} ${srcdir}/latex/tutorial.ps ${docdir}/
+
+# Removes all installed documentation files from the system:
+uninstall:
+       rm -rf ${docdir}
+
+# The next targets should only be called in case of emergency by developers, 
+# since the complete documentation is not normally rebuilt.  In any case, they
+# should only be called from people who know what they are doing and never 
+# from top-level Makefile's targets clean and distclean.
+clean:
+       rm -rf ${srcdir}/tutorial ${srcdir}/reference ${srcdir}/latex
+       rm -f tutorial.sgml
+
+distclean: clean
+       rm -f Makefile
+
+# Special dummy targets:
+.SUFFIXES: .fig .eps .png
+.PHONY: all clean distclean reference tutorial
+.SILENT: all reference tutorial_html tutorial_tex
+
+# Suffix rules:
+.fig.eps :
+       @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi
+       if [ "${FIG2DEV}" ]; then \
+               ${FIG2DEV} -L ps -m 0.8 $< ${srcdir}/latex/$@; \
+       else \
+               echo "warning: fig2dev was not found by configure"; \
+       fi
+.fig.png :
+       @ if [ ! -d ${srcdir}/tutorial ]; then mkdir ${srcdir}/tutorial; fi
+       if [ "${FIG2DEV}" ]; then \
+               ${FIG2DEV} -L png $< ${srcdir}/tutorial/$@; \
+       else \
+               echo "warning: fig2dev was not found by configure"; \
+       fi
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644 (file)
index 0000000..ebe33f6
--- /dev/null
@@ -0,0 +1,168 @@
+# This is the prototype Makefile for all of GiNaC's documentation.  It tries to
+# be tolerant---if some tools were not found it skips the built of that part
+# of documentation and tries to continue.
+
+# Substitution variables from configure skript:
+# Here come the usual install directories in GNU-configure fashion:
+prefix = @prefix@
+docdir = @datadir@/doc/GiNaC
+srcdir = @srcdir@
+# Dimitri van Heesch's Doxygen is needed for developer's resource:
+DOXYGEN = @DOXYGEN@
+# LaTeX and friends are needed for processing developer's resource for print:
+LATEX = @LATEX@
+MAKEINDEX = @MAKEINDEX@
+DVIPS = @DVIPS@
+FIG2DEV = @FIG2DEV@
+# Jade and friends needed for generating the tutorial:
+JADE = @JADE@
+JADETEX = @JADETEX@
+# Arguments for Jade and friends (does anybody know how to find them out?)
+# JADEARGS_TEX = -t tex -o tutorial.tex -d /usr/lib/dsssl/stylesheets/docbook/print/docbook.dsl
+JADEARGS_TEX = -t tex -o tutorial.tex -d /usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/print/docbook.dsl
+# JADEARGS_HTML = -t sgml -d /usr/lib/dsssl/stylesheets/docbook/html/docbook.dsl
+JADEARGS_HTML = -t sgml -d /usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/html/docbook.dsl
+# Autoconf macro AC_PROC_INSTALL sets these:
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+# All LaTeX builds will take place in a separate subdirectory:
+VPATH = @srcdir@:@srcdir@/latex:@srcdir@/tutorial
+
+# default target:
+all: reference tutorial
+
+# REFERENCE:
+# This section produces HTML'ed and TeX'ed developer's reference from the
+# sources with a JavaDoc-like tool (in this case doxygen):
+reference_html:
+       @ if [ ! -d ${srcdir}/reference ]; then mkdir ${srcdir}/reference; fi
+       @ if [ "${DOXYGEN}" ]; then \
+               echo "Running ${DOXYGEN} ./DoxyfileHTML..."; \
+               cd ..; ${DOXYGEN} ./doc/DoxyfileHTML; \
+       else \
+               echo "warning: target reference_html disabled by configuration"; \
+       fi
+
+reference.tex:
+       @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi
+       @ if [ "${DOXYGEN}" ]; then \
+               echo "Running ${DOXYGEN} ./DoxyfileTEX..."; \
+               cd ..; ${DOXYGEN} ./doc/DoxyfileTEX; \
+       else \
+               echo "warning: target reference.tex disabled by configuration"; \
+       fi
+       - mv ${srcdir}/latex/refman.tex ${srcdir}/latex/reference.tex 
+
+reference.dvi: reference.tex
+       @ if [ "${LATEX}" -a "${MAKEINDEX}" ]; then \
+               cd latex; \
+               ${LATEX} reference.tex && \
+               ${MAKEINDEX} reference.idx && \
+               ${LATEX} reference.tex; \
+       else \
+               echo "warning: target reference.dvi disabled by configuration"; \
+       fi
+
+reference.ps: reference.dvi
+       @ if [ "${DVIPS}" ]; then \
+               echo "Running ${DVIPS} -o reference.ps reference.dvi..."; \
+               cd latex; ${DVIPS} -o reference.ps reference.dvi; \
+       else \
+               echo "warning: target reference.ps disabled by configuration"; \
+       fi
+
+reference: reference_html reference.ps
+
+# TUTORIAL:
+# This section produces HTML'ed and TeX'ed versions of the tutorial using a
+# SGML to TeX converter (in this case jade).  As a dirty hack, we are doing
+# some regexpese to tutorial.sgml prior to parsing it, in order to allow for
+# different graphics output.  This seems to be an ugly limitation of docbook...
+
+EPS = classhierarchy.eps rep_naive.eps rep_pair.eps
+PNG = classhierarchy.png rep_naive.png rep_pair.png
+
+tutorial/index.html: tutorial.sgml.in ${PNG}
+       @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi
+       @ if [ "${JADE}" ]; then \
+               sed -e 's/graext/png/g' -e 's/GRAEXT/GIF/g' tutorial.sgml.in > tutorial.sgml; \
+               echo "Running ${JADE} ${JADEARGS_HTML} tutorial.sgml..."; \
+               cd tutorial/; ${JADE} ${JADEARGS_HTML} ../tutorial.sgml; \
+               if [ -f book1.html ]; then cp book1.html index.html; fi; \
+       else \
+               echo "warning: target tutorial_html disabled by configuration"; \
+       fi
+
+tutorial.tex: tutorial.sgml.in ${EPS}
+       @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi
+       @ if [ "${JADE}" -a "${LATEX}" ]; then \
+               sed -e 's/graext/eps/g' -e 's/GRAEXT/EPS/g' tutorial.sgml.in > tutorial.sgml; \
+               echo "Running ${JADE} ${JADEARGS_TEX} tutorial.sgml..."; \
+               cd latex; ${JADE} ${JADEARGS_TEX} ../tutorial.sgml ; \
+       else \
+               echo "warning: target tutorial.tex disabled by configuration"; \
+       fi
+
+tutorial.dvi: tutorial.tex
+       @ if [ "${JADETEX}" ]; then \
+               echo "Running ${JADETEX} tutorial.tex..."; \
+               cd latex; ${JADETEX} tutorial.tex && ${JADETEX} tutorial.tex && ${JADETEX} tutorial.tex; \
+       else \
+               echo "warning: target tutorial.dvi disabled by configuration"; \
+       fi
+
+tutorial.ps: tutorial.dvi
+       @ if [ "${DVIPS}" ]; then \
+               echo "Running ${DVIPS} tutorial.dvi -o tutorial.ps..."; \
+               cd latex; ${DVIPS} tutorial.dvi -o tutorial.ps; \
+       else \
+               echo "warning: target tutorial.ps disabled by configuration"; \
+       fi
+
+tutorial:      tutorial/index.html tutorial.ps
+
+# Target for installing all generated documentation files on the system.
+# (Foolproof: installs what we got, even if one or more targets failed.)
+install:
+       - ${INSTALL} -d ${docdir}/reference/
+       - ${INSTALL_DATA} ${srcdir}/reference/* ${docdir}/reference/
+       - ${INSTALL_DATA} ${srcdir}/latex/reference.ps ${docdir}/
+       - ${INSTALL} -d ${docdir}/tutorial/
+       - ${INSTALL_DATA} ${srcdir}/tutorial/* ${docdir}/tutorial/
+       - ${INSTALL_DATA} ${srcdir}/latex/tutorial.ps ${docdir}/
+
+# Removes all installed documentation files from the system:
+uninstall:
+       rm -rf ${docdir}
+
+# The next targets should only be called in case of emergency by developers, 
+# since the complete documentation is not normally rebuilt.  In any case, they
+# should only be called from people who know what they are doing and never 
+# from top-level Makefile's targets clean and distclean.
+clean:
+       rm -rf ${srcdir}/tutorial ${srcdir}/reference ${srcdir}/latex
+       rm -f tutorial.sgml
+
+distclean: clean
+       rm -f Makefile
+
+# Special dummy targets:
+.SUFFIXES: .fig .eps .png
+.PHONY: all clean distclean reference tutorial
+.SILENT: all reference tutorial_html tutorial_tex
+
+# Suffix rules:
+.fig.eps :
+       @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi
+       if [ "${FIG2DEV}" ]; then \
+               ${FIG2DEV} -L ps -m 0.8 $< ${srcdir}/latex/$@; \
+       else \
+               echo "warning: fig2dev was not found by configure"; \
+       fi
+.fig.png :
+       @ if [ ! -d ${srcdir}/tutorial ]; then mkdir ${srcdir}/tutorial; fi
+       if [ "${FIG2DEV}" ]; then \
+               ${FIG2DEV} -L png $< ${srcdir}/tutorial/$@; \
+       else \
+               echo "warning: fig2dev was not found by configure"; \
+       fi
diff --git a/doc/classhierarchy.fig b/doc/classhierarchy.fig
new file mode 100644 (file)
index 0000000..fef6907
--- /dev/null
@@ -0,0 +1,117 @@
+#FIG 3.2
+Landscape
+Center
+Metric
+A4      
+100.00
+Single
+-2
+1200 2
+5 1 1 2 0 7 100 0 -1 4.000 0 0 1 0 1896.500 2807.128 791 579 1973 321 3002 579
+       1 1 1.00 68.57 137.14
+6 4853 2533 5779 2790
+2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5
+        4853 2533 5779 2533 5779 2790 4853 2790 4853 2533
+4 1 0 99 0 0 14 0.0000 4 150 555 5316 2739 matrix\001
+-6
+6 4853 2070 5779 2327
+2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5
+        4853 2070 5779 2070 5779 2327 4853 2327 4853 2070
+4 1 0 99 0 0 14 0.0000 4 150 705 5316 2276 numeric\001
+-6
+6 4853 1607 5779 1864
+2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5
+        4853 1607 5779 1607 5779 1864 4853 1864 4853 1607
+4 1 0 99 0 0 14 0.0000 4 135 735 5316 1813 constant\001
+-6
+6 585 2019 1099 2276
+2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5
+        585 2019 1099 2019 1099 2276 585 2276 585 2019
+4 1 0 99 0 0 14 0.0000 4 150 315 842 2224 add\001
+-6
+6 1511 2019 2025 2276
+2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5
+        1511 2019 2025 2019 2025 2276 1511 2276 1511 2019
+4 1 0 99 0 0 14 0.0000 4 150 315 1768 2224 mul\001
+-6
+6 996 1144 2025 1401
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        2025 1144 996 1144 996 1401 2025 1401 2025 1144
+4 1 0 99 0 0 14 0.0000 4 195 840 1511 1350 expairseq\001
+-6
+6 3053 630 3876 887
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        3053 630 3876 630 3876 887 3053 887 3053 630
+4 1 0 99 0 0 14 0.0000 4 150 450 3465 836 basic\001
+-6
+6 225 463 739 720
+2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5
+        225 463 739 463 739 720 225 720 225 463
+4 1 0 99 0 0 14 0.0000 4 105 210 482 668 ex\001
+-6
+6 2160 1498 2880 1755
+2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5
+        2160 1498 2880 1498 2880 1755 2160 1755 2160 1498
+4 1 0 99 0 0 14 0.0000 4 150 555 2520 1704 power\001
+-6
+6 2475 1935 3330 2205
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        2475 1948 3330 1948 3330 2205 2475 2205 2475 1948
+4 1 0 99 0 0 14 0.0000 4 150 690 2899 2154 exprseq\001
+-6
+6 2250 2925 3195 3195
+2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5
+        2250 2925 3195 2925 3195 3195 2250 3195 2250 2925
+4 1 0 99 0 0 14 0.0000 4 150 690 2719 3131 function\001
+-6
+6 1626 2533 2449 2790
+2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5
+        1626 2533 2449 2533 2449 2790 1626 2790 1626 2533
+4 1 0 99 0 0 14 0.0000 4 150 525 2038 2739 ncmul\001
+-6
+6 3060 2385 3780 2655
+2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5
+        3060 2385 3780 2385 3780 2655 3060 2655 3060 2385
+4 1 0 99 0 0 14 0.0000 4 150 510 3394 2591 series\001
+-6
+6 4860 1119 5786 1376
+2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5
+        4860 1119 5786 1119 5786 1376 4860 1376 4860 1119
+4 1 0 99 0 0 14 0.0000 4 195 615 5323 1324 symbol\001
+-6
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2
+       1 1 1.00 60.00 120.00
+        3825 945 4802 2121
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2
+       1 1 1.00 60.00 120.00
+        3053 939 2076 1144
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2
+       1 1 1.00 60.00 120.00
+        3156 939 2693 1453
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2
+       1 1 1.00 60.00 120.00
+        3722 939 4802 2584
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2
+       1 1 1.00 60.00 120.00
+        3915 945 4815 1665
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2
+       1 1 1.00 60.00 120.00
+        3208 939 3105 1916
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2
+       1 1 1.00 60.00 120.00
+        2693 2276 2231 2481
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2
+       1 1 1.00 60.00 120.00
+        3371 937 3465 2340
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2
+       1 1 1.00 60.00 120.00
+        2825 2282 2677 2886
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2
+       1 1 1.00 60.00 120.00
+        1459 1453 894 1967
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2
+       1 1 1.00 60.00 120.00
+        1562 1453 1716 1967
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2
+       1 1 1.00 60.00 120.00
+        3915 881 4815 1215
diff --git a/doc/powerlaws.tex b/doc/powerlaws.tex
new file mode 100644 (file)
index 0000000..75ce8c9
--- /dev/null
@@ -0,0 +1,155 @@
+\documentclass{article}
+
+\begin{document}
+
+\section{Power Laws}
+
+\subsection{Definitions}
+
+Definitions for power and log:
+\begin{equation}
+x^a \equiv e^{a \ln x}
+\end{equation}
+\begin{equation}
+\ln x \equiv \ln |x| + i \arg(x) \mbox{ where } -\pi < \arg(x) \le \pi
+\end{equation}
+
+\subsection{General rules}
+
+\begin{equation}
+e^x e^y = e^{x+y}
+\end{equation}
+for arbitrary complex $x$ and $y$
+
+\begin{equation}
+x^{-a} = \frac{1}{x^a}
+\end{equation}
+for arbitrary complex $x$ and $a$
+
+\subsection{$(ax)^b=a^b x^b$}
+
+\subsubsection{$b$ integer, $x$ and $a$ arbitrary complex}
+
+assume $b>0$
+
+\begin{eqnarray}
+(ax)^b & = & \underbrace{(ax) \cdots (ax)}_{b \times}
+\nonumber\\
+& = & \underbrace{a \cdots a}_{b \times}
+      \underbrace{x \cdots x}_{b \times}
+\nonumber\\
+& = & a^b x^b \mbox{ q.e.d.}
+\end{eqnarray}
+
+if $b<0$ (so $b=-|b|$)
+\begin{eqnarray}
+(ax)^b & = & \frac{1}{(ax)^{|b|}}
+\nonumber\\
+& = & \frac{1}{a^{|b|} x^{|b|}}
+\nonumber\\
+& = & a^{-|b|} x^{-|b|}
+\nonumber\\
+& = & a^b x^b
+\end{eqnarray}
+
+\subsubsection{$a>0$, $x$ and $b$ arbitrary complex}
+
+\begin{eqnarray}
+(ax)^b & = & e^{b \ln(ax)}
+\nonumber\\
+& = & e^{b (\ln |ax| + i \arg(ax))}
+\end{eqnarray}
+
+if $a$ is real and positive:
+\begin{equation}
+\ln |ax| = \ln |a| + \ln |x| = \ln a + \ln |x|
+\end{equation}
+and 
+\begin{equation}
+\arg(ax) = \arg(x)
+\end{equation}
+
+So
+\begin{eqnarray}
+e^{b (\ln |ax| + i \arg(ax))} & = &
+e^{b (\ln a + \ln |x| + i \arg(x))}
+\nonumber\\
+& = & e^{b (\ln a + \ln x)}
+\nonumber\\
+& = & e^{b \ln a} e^{b \ln x}
+\nonumber\\
+& = & a^b x^b \mbox{ q.e.d.}
+\end{eqnarray}
+
+\subsection{$(x^a)^b = x^{ab}$}
+
+\subsubsection{$b$ integer, $x$ and $a$ arbitrary complex}
+
+assume $b>0$
+
+\begin{eqnarray}
+(x^a)^b & = & \underbrace{(x^a) \cdots (x^a)}_{b \times}
+\nonumber\\
+& = & \underbrace{e^{a \ln x} \cdots e^{a \ln x}}_{b \times}
+\nonumber\\
+& = & e^{\underbrace{\scriptstyle a \ln x + \dots + a \ln x}_{b \times}}
+\nonumber\\
+& = & e^{a b \ln x}
+\nonumber\\
+& = & x^{ab} \mbox{ q.e.d.}
+\end{eqnarray}
+
+if $b<0$ (so $b=-|b|$)
+\begin{eqnarray}
+(x^a)^b & = & \frac{1}{(x^a)^{|b|}}
+\nonumber\\
+& = & \frac{1}{x^{a|b|}}
+\nonumber\\
+& = & x^{-a|b|}
+\nonumber\\
+& = & x^{ab}
+\end{eqnarray}
+
+\subsubsection{$-1 < a \le 1$, $x$ and $b$ arbitrary complex}
+
+We have
+\begin{equation}
+x^a=e^{a \ln|x| + ia\arg(x)}
+\end{equation}
+if $a$ is real
+\begin{equation}
+|x^a|=e^{a\ln|x|}
+\end{equation}
+and
+\begin{equation}
+\arg(x^a)-a\arg(x)=2k\pi
+\end{equation}
+now if $-1 < a \le 1$, then $-\pi < a\arg(x) \le \pi$,
+and so $k=0$, i.e.
+\begin{equation}
+\arg(x^a)=a\arg(x)
+\end{equation}
+(Note that for $a=-1$ this may not be true, as $-1 \arg(x)$ may be equal to $-\pi$.)
+So
+\begin{eqnarray}
+\ln(x^a) & = & \ln|x^a| + i\arg(x^a)
+\nonumber\\
+& = & \ln (e^{a\ln|x|})+ia\arg(x)
+\nonumber\\
+& = & a \ln |x| + ia\arg(x) \mbox{ (because $a\ln|x|$ is real)}
+\nonumber\\
+& = & a\ln x
+\end{eqnarray}
+Hence
+\begin{eqnarray}
+(x^a)^b & = & e^{b\ln x^a}
+\nonumber\\
+& = & e^{ba\ln x}
+\nonumber\\
+& = & x^{ab} \mbox{ q.e.d.}
+\end{eqnarray}
+
+proof contributed by Adam Strzebonski from Wolfram Research
+({\tt adams@wolfram.com}) in newsgroup {\tt sci.math.symbolic}.
+
+\end{document}
\ No newline at end of file
diff --git a/doc/rep_naive.fig b/doc/rep_naive.fig
new file mode 100644 (file)
index 0000000..63292a1
--- /dev/null
@@ -0,0 +1,104 @@
+#FIG 3.2
+Landscape
+Center
+Metric
+A4      
+100.00
+Single
+-2
+1200 2
+6 1530 3330 1890 3690
+1 3 0 1 0 7 100 0 20 0.000 1 0.0000 1725 3525 165 165 1725 3525 1890 3520
+4 1 0 99 0 0 14 0.0000 4 105 105 1725 3595 a\001
+-6
+6 2520 4005 2880 4365
+1 3 0 1 0 7 100 0 20 0.000 1 0.0000 2715 4200 165 165 2715 4200 2880 4195
+4 1 0 99 0 0 14 0.0000 4 150 105 2715 4270 2\001
+-6
+6 2970 4005 3330 4365
+1 3 0 1 0 7 100 0 20 0.000 1 0.0000 3165 4200 165 165 3165 4200 3330 4195
+4 1 0 99 0 0 14 0.0000 4 150 105 3165 4270 b\001
+-6
+6 3870 4005 4230 4365
+1 3 0 1 0 7 100 0 20 0.000 1 0.0000 4065 4200 165 165 4065 4200 4230 4195
+4 1 0 99 0 0 14 0.0000 4 150 240 4065 4270 -1\001
+-6
+6 4320 4005 4680 4365
+1 3 0 1 0 7 100 0 20 0.000 1 0.0000 4515 4200 165 165 4515 4200 4680 4195
+4 1 0 99 0 0 14 0.0000 4 105 105 4515 4270 c\001
+-6
+6 2610 2700 3240 3060
+6 2610 2700 3240 2970
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        2610 2700 3240 2700 3240 2970 2610 2970 2610 2700
+4 1 0 99 0 0 14 0.0000 4 150 315 2925 2906 add\001
+-6
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        2610 2970 3240 2970 3240 3060 2610 3060 2610 2970
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        2610 2970 2820 2970 2820 3060 2610 3060 2610 2970
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        3030 2970 3240 2970 3240 3060 3030 3060 3030 2970
+-6
+6 2610 3375 3240 3735
+6 2610 3375 3240 3645
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        2610 3375 3240 3375 3240 3645 2610 3645 2610 3375
+4 1 0 99 0 0 14 0.0000 4 150 315 2925 3581 mul\001
+-6
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        2610 3645 3240 3645 3240 3735 2610 3735 2610 3645
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+        2925 3645 2925 3735
+-6
+6 3960 3375 4590 3735
+6 3960 3375 4590 3645
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        3960 3375 4590 3375 4590 3645 3960 3645 3960 3375
+4 1 0 99 0 0 14 0.0000 4 150 315 4275 3581 mul\001
+-6
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        3960 3645 4590 3645 4590 3735 3960 3735 3960 3645
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+        4275 3645 4275 3735
+-6
+6 1260 2025 1890 2385
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        1260 2025 1890 2025 1890 2295 1260 2295 1260 2025
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        1260 2295 1890 2295 1890 2385 1260 2385 1260 2295
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2
+        1575 2385 1575 2295
+4 1 0 99 0 0 14 0.0000 4 150 315 1575 2231 mul\001
+-6
+6 225 2685 555 3015
+1 3 0 1 0 7 100 0 20 0.000 1 0.0000 390 2850 165 165 390 2850 555 2845
+4 1 0 99 0 0 14 0.0000 4 150 105 390 2920 d\001
+-6
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        2700 3060 1845 3375
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        2925 3060 2925 3375
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        3150 3060 4005 3375
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        1799 2387 2654 2702
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        1350 2385 495 2700
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        2790 3735 2745 4005
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        3075 3733 3120 4003
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        4133 3734 4088 4004
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        4387 3732 4432 4002
diff --git a/doc/rep_pair.fig b/doc/rep_pair.fig
new file mode 100644 (file)
index 0000000..7160eef
--- /dev/null
@@ -0,0 +1,98 @@
+#FIG 3.2
+Landscape
+Center
+Metric
+A4      
+100.00
+Single
+-2
+1200 2
+6 1260 135 1890 585
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        1260 135 1890 135 1890 405 1260 405 1260 135
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        1260 405 1890 405 1890 495 1260 495 1260 405
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        1260 495 1890 495 1890 585 1260 585 1260 495
+2 1 0 1 0 7 99 0 -1 0.000 0 0 -1 0 0 2
+        1575 585 1575 405
+4 1 0 99 0 0 14 0.0000 4 150 315 1575 341 mul\001
+-6
+6 2610 900 3240 1170
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        2610 900 3240 900 3240 1170 2610 1170 2610 900
+4 1 0 99 0 0 14 0.0000 4 150 315 2925 1106 add\001
+-6
+6 2610 1260 3240 1350
+2 2 0 1 0 7 99 0 20 0.000 0 0 -1 0 0 5
+        2610 1260 2820 1260 2820 1350 2610 1350 2610 1260
+2 2 0 1 0 7 99 0 20 0.000 0 0 -1 0 0 5
+        3030 1260 3240 1260 3240 1350 3030 1350 3030 1260
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        2610 1260 3240 1260 3240 1350 2610 1350 2610 1260
+-6
+6 2610 1170 3240 1260
+2 2 0 1 0 7 99 0 20 0.000 0 0 -1 0 0 5
+        2610 1170 2820 1170 2820 1260 2610 1260 2610 1170
+2 2 0 1 0 7 99 0 20 0.000 0 0 -1 0 0 5
+        3030 1170 3240 1170 3240 1260 3030 1260 3030 1170
+2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5
+        2610 1170 3240 1170 3240 1260 2610 1260 2610 1170
+-6
+6 225 900 585 1710
+6 225 930 555 1260
+1 3 0 1 0 7 100 0 20 0.000 1 0.0000 390 1095 165 165 390 1095 555 1090
+4 1 0 99 0 0 14 0.0000 4 150 105 390 1165 d\001
+-6
+6 225 1350 585 1710
+1 3 0 1 0 7 100 0 20 0.000 1 0.0000 390 1545 165 165 390 1545 555 1540
+4 1 0 99 0 0 14 0.0000 4 150 105 390 1615 1\001
+-6
+-6
+6 1575 2115 1935 2475
+1 3 0 1 0 7 100 0 20 0.000 1 0.0000 1740 2310 165 165 1740 2310 1905 2305
+4 1 0 99 0 0 14 0.0000 4 150 105 1740 2380 1\001
+-6
+6 1575 1665 1935 2025
+1 3 0 1 0 7 100 0 20 0.000 1 0.0000 1740 1860 165 165 1740 1860 1905 1855
+4 1 0 99 0 0 14 0.0000 4 105 105 1740 1930 a\001
+-6
+6 2745 1665 3105 2025
+1 3 0 1 0 7 100 0 20 0.000 1 0.0000 2910 1860 165 165 2910 1860 3075 1855
+4 1 0 99 0 0 14 0.0000 4 150 105 2910 1930 b\001
+-6
+6 2745 2115 3105 2475
+1 3 0 1 0 7 100 0 20 0.000 1 0.0000 2910 2310 165 165 2910 2310 3075 2305
+4 1 0 99 0 0 14 0.0000 4 150 105 2910 2380 2\001
+-6
+6 3960 1665 4320 2025
+1 3 0 1 0 7 100 0 20 0.000 1 0.0000 4125 1860 165 165 4125 1860 4290 1855
+4 1 0 99 0 0 14 0.0000 4 105 105 4125 1930 c\001
+-6
+6 3960 2115 4320 2475
+1 3 0 1 0 7 100 0 20 0.000 1 0.0000 4125 2310 165 165 4125 2310 4290 2305
+4 1 0 99 0 0 14 0.0000 4 150 240 4125 2380 -1\001
+-6
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        1351 587 496 902
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        1803 577 2658 892
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        2697 1342 1842 1657
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        3148 1347 4003 1662
+2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2
+       0 0 1.00 60.00 120.00
+        2925 1350 2925 1665
+2 2 2 1 0 7 100 0 -1 3.000 0 0 -1 0 0 5
+        180 900 585 900 585 1755 180 1755 180 900
+2 2 2 1 0 7 100 0 -1 3.000 0 0 -1 0 0 5
+        1530 1665 1935 1665 1935 2520 1530 2520 1530 1665
+2 2 2 1 0 7 100 0 -1 3.000 0 0 -1 0 0 5
+        2700 1665 3105 1665 3105 2520 2700 2520 2700 1665
+2 2 2 1 0 7 100 0 -1 3.000 0 0 -1 0 0 5
+        3915 1665 4320 1665 4320 2520 3915 2520 3915 1665
diff --git a/doc/tutorial.sgml.in b/doc/tutorial.sgml.in
new file mode 100644 (file)
index 0000000..5d35153
--- /dev/null
@@ -0,0 +1,1544 @@
+<!DOCTYPE Book PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
+
+<book>
+<title>GiNaC Tutorial</title>
+<bookinfo>
+<subtitle>An open framework for symbolic computation within the C++ programming language</subtitle>
+<bookbiblio>
+<authorgroup>
+  <collab>
+    <collabname>The GiNaC Group</collabname>
+  </collab>
+  <author>
+    <firstname>Christian</firstname><surname>Bauer</surname>
+    <affiliation>
+      <address><email>Christian.Bauer@Uni-Mainz.DE</email></address>
+    </affiliation>
+  </author>
+  <author>
+    <firstname>Alexander</firstname><surname>Frink</surname>
+    <affiliation>
+      <address><email>Alexander.Frink@Uni-Mainz.DE</email></address>
+    </affiliation>
+  </author>
+  <author>
+    <firstname>Richard</firstname><othername>B.</othername><surname>Kreckel</surname>
+    <affiliation>
+      <address><email>Richard.Kreckel@Uni-Mainz.DE</email></address>
+    </affiliation>
+  </author>
+  <author>
+    <surname>Others</surname>
+    <affiliation>
+      <address><email>whoever@ThEP.Physik.Uni-Mainz.DE</email></address>
+    </affiliation>
+  </author>
+</authorgroup>
+</bookbiblio>
+</bookinfo>
+
+<preface>
+<title>Introduction</title>
+
+<para>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.</para>
+
+<para>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.  The generated HTML
+documenatation is included in the distributed sources (subdir
+<literal>doc/reference/</literal>) or can be accessed directly at URL
+<ulink
+url="http://wwwthep.physik.uni-mainz.de/GiNaC/reference/"><literal>http://wwwthep.physik.uni-mainz.de/GiNaC/reference/</literal></ulink>.
+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.
+</para>
+
+<sect1><title>License</title>
+
+<para>The GiNaC framework for symbolic computation within the C++
+programming language is Copyright (C) 1999 Johannes Gutenberg
+Universit&auml;t Mainz, Germany.</para>
+
+<para>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.</para>
+
+<para>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.</para>
+
+<para>You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA.</para>
+
+</preface>
+
+<chapter>
+<title>A Tour of GiNaC</title>
+
+<para>This quick tour of GiNaC wants to rise your interest in in the
+subsequent chapters by showing off a bit.  Please excuse us if it
+leaves many open questions.</para>
+
+<sect1><title>How to use it from within C++</title> <para>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
+pointless) bivariate polynomial with some large coefficients:
+<example>
+<title>My first GiNaC program (a bivariate polynomial)</title>
+<programlisting>
+#include &lt;GiNaC/ginac.h&gt;
+
+int main()
+{
+    symbol x("x"), y("y");
+    ex poly;
+
+    for (int i=0; i<3; ++i)
+        poly += factorial(i+16)*pow(x,i)*pow(y,2-i);
+
+    cout &lt;&lt; poly &lt;&lt; endl;
+    return 0;
+}
+</programlisting>
+<para>Assuming the file is called <literal>hello.cc</literal>, on 
+our system we can compile and run it like this:</para>
+<screen>
+<prompt>sysprompt></prompt> c++ hello.cc -o hello -lcln -lginac
+<prompt>sysprompt></prompt> ./hello
+355687428096000*x*y+20922789888000*y^2+6402373705728000*x^2
+</screen>
+</example>
+</para>
+
+<para>Next, there is a more meaningful C++ program that calls a
+function which generates Hermite polynomials in a specified free
+variable.
+<example>
+<title>My second GiNaC program (Hermite polynomials)</title>
+<programlisting>
+#include &lt;GiNaC/ginac.h&gt;
+
+ex HermitePoly(symbol x, int deg)
+{
+    ex HKer=exp(-pow(x,2));
+    // uses the identity H_n(x) == (-1)^n exp(x^2) (d/dx)^n exp(-x^2) 
+    return normal(pow(-1,deg) * diff(HKer, x, deg) / HKer);
+}
+
+int main()
+{
+    symbol z("z");
+
+    for (int i=0; i<6; ++i)
+        cout &lt;&lt; "H_" &lt;&lt; i &lt;&lt; "(z) == " &lt;&lt; HermitePoly(z,i) &lt;&lt; endl;
+
+    return 0;
+}
+</programlisting>
+<para>When run, this will type out</para>
+<screen>
+H_0(z) == 1
+H_1(z) == 2*z
+H_2(z) == 4*z^2-2
+H_3(z) == -12*z+8*z^3
+H_4(z) == -48*z^2+16*z^4+12
+H_5(z) == 120*z-160*z^3+32*z^5
+</screen>
+</example>
+This method of generating the coefficients is of course far from
+optimal for production purposes.</para>
+
+<para>In order to show some more examples of what GiNaC can do we
+will now use <literal>ginsh</literal>, a simple GiNaC interactive
+shell that provides a convenient window into GiNaC's capabilities.
+</para></sect1>
+
+<sect1><title>What it can do for you</title>
+
+<para>After invoking <literal>ginsh</literal> 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 concise description of the
+<literal>ginsh</literal> syntax we refer to its accompanied 
+man-page.</para>
+
+<para>It can manipulate arbitrary precision integers in a very fast
+way.  Rational numbers are automatically converted to fractions of
+coprime integers:
+<screen>
+> x=3^150;
+369988485035126972924700782451696644186473100389722973815184405301748249
+> y=3^149;
+123329495011708990974900260817232214728824366796574324605061468433916083
+> x/y;
+3
+> y/x;
+1/3
+</screen>
+</para>
+
+<para>All numbers occuring in GiNaC's expressions can be converted
+into floating point numbers with the <literal>evalf</literal> method,
+to arbitrary accuracy:
+<screen>
+> evalf(1/7);
+0.14285714285714285714
+> Digits=150;
+150
+> evalf(1/7);
+0.1428571428571428571428571428571428571428571428571428571428571428571428
+5714285714285714285714285714285714285
+</screen>
+</para>
+
+<para>Exact numbers other than rationals that can be manipulated in
+GiNaC include predefined constants like Archimedes' Pi.  They can both
+be used in symbolic manipulations (as an exact number) as well as in
+numeric expressions (as an inexact number):
+<screen>
+> a=Pi^2+x;
+x+Pi^2
+> evalf(a);
+x+9.869604401089358619L0
+> x=2;
+2
+> evalf(a);
+11.869604401089358619L0
+</screen>
+</para>
+
+<para>Built-in functions evaluate immediately to exact numbers if
+this is possible.  Conversions that can be safely performed are done
+immediately; conversions that are not generally valid are not done:
+<screen>
+> cos(42*Pi);
+1
+> cos(acos(x));
+x
+> acos(cos(x));
+acos(cos(x))
+</screen>
+(Note that converting the last input to <literal>x</literal> would
+allow one to conclude that <literal>42*Pi</literal> is equal to
+<literal>0</literal>.)</para>
+
+<para>Linear equation systems can be solved along with basic linear
+algebra manipulations over symbolic expressions:
+<screen>
+> lsolve(a+x*y==z,x);
+y^(-1)*(z-a);
+lsolve([3*x+5*y == 7, -2*x+10*y == -5], [x, y]);
+[x==19/8,y==-1/40]
+> M = [[ [[1, 3]], [[-3, 2]] ]];
+[[ [[1,3]], [[-3,2]] ]]
+> determinant(M);
+11
+> charpoly(M,lambda);
+lambda^2-3*lambda+11
+</screen>
+</para>
+
+<para>Multivariate polynomials and rational functions may be expanded,
+collected and normalized (i.e. converted to a ratio of two coprime 
+polynomials):
+<screen>
+> a = x^4 + 2*x^2*y^2 + 4*x^3*y + 12*x*y^3 - 3*y^4;
+-3*y^4+x^4+12*x*y^3+2*x^2*y^2+4*x^3*y
+> b = x^2 + 4*x*y - y^2;
+-y^2+x^2+4*x*y
+> expand(a*b);
+3*y^6+x^6-24*x*y^5+43*x^2*y^4+16*x^3*y^3+17*x^4*y^2+8*x^5*y
+> collect(a*b,x);
+3*y^6+48*x*y^4+2*x^2*y^2+x^4*(-y^2+x^2+4*x*y)+4*x^3*y*(-y^2+x^2+4*x*y)
+> normal(a/b);
+3*y^2+x^2
+</screen>
+</para>
+
+<para>
+You can differentiate functions and expand them as Taylor or Laurent 
+series (the third argument of series is the evaluation point, the 
+fourth defines the order):
+<screen>
+> diff(tan(x),x);
+tan(x)^2+1
+> series(sin(x),x,0,4);
+x-1/6*x^3+Order(x^4)
+> series(1/tan(x),x,0,4);
+x^(-1)-1/3*x+Order(x^2)
+</screen>
+</para>
+
+</sect1>
+
+</chapter>
+
+
+<chapter>
+<title>Installation</title>
+
+<para>GiNaC's installation follows the spirit of most GNU software. It is
+easily installed on your system by three steps: configuration, build,
+installation.</para>
+
+<sect1 id="ind123"><title id="CLN-main">Prerequistes</title>
+
+<para>In order to install GiNaC on your system, some prerequistes need
+to be met.  First of all, you need to have a C++-compiler adhering to
+the ANSI-standard <citation>ISO/IEC 14882:1998(E)</citation>.  We used
+<literal>GCC</literal> for development so if you have a different
+compiler you are on your own.  For the configuration to succeed you
+need a Posix compliant shell installed in <literal>/bin/sh</literal>,
+GNU <literal>bash</literal> is fine.  Perl is needed by the built
+process as well, since some of the source files are automatically
+generated by Perl scripts.  Last but not least, Bruno Haible's library
+<literal>CLN</literal> is extensively used and needs to be installed
+on your system.  Please get it from <ulink
+url="ftp://ftp.santafe.edu/pub/gnu/"><literal>ftp://ftp.santafe.edu/pub/gnu/</literal></ulink>
+or from <ulink
+url="ftp://ftp.ilog.fr/pub/Users/haible/gnu/"><literal>ftp://ftp.ilog.fr/pub/Users/haible/gnu/</literal></ulink>
+(it is covered by GPL) and install it prior to trying to install
+GiNaC.  The configure script checks if it can find it and if it cannot
+it will refuse to continue.</para></sect1>
+
+<sect1><title>Configuration</title>
+
+<para>To configure GiNaC means to prepare the source distribution for
+building.  It is done via a shell script called
+<literal>configure</literal> that is shipped with the sources.
+(Actually, this script is by itself created with GNU Autoconf from the
+files <literal>configure.in</literal> and
+<literal>aclocal.m4</literal>.)  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 <literal>--help</literal> option.  The most important ones
+will be shortly described in what follows:
+<itemizedlist>
+  <listitem>
+    <para><literal>--enable-shared</literal>: When given, this option
+    switches on the build of a shared library, i.e. a
+    <literal>.so</literal>-file. A static libarary (i.e. a
+    <literal>.a</literal>-file) is still built. For this to succeed,
+    GNU libtool needs to be installed on your system. Hence,
+    <literal>configure</literal> checks if it can find an executable
+    <literal>libtool</literal> in the <literal>PATH</literal>. If it
+    doesn't this option is ignored and the default restored, which
+    means that only a static library will be build.</para>
+  </listitem>
+  <listitem>
+    <para><literal>--prefix=</literal><emphasis>PREFIX</emphasis>: The
+    directory where the compiled library and headers are installed. It
+    defaults to <literal>/usr/local</literal> which means that the
+    library is installed in the directory
+    <literal>/usr/local/lib</literal> and the header files in
+    <literal>/usr/local/include/GiNaC</literal> and the documentation
+    (like this one) into <literal>/usr/local/share/doc/GiNaC</literal>.</para>
+  </listitem>
+  <listitem>
+    <para><literal>--libdir=</literal><emphasis>LIBDIR</emphasis>: Use
+    this option in case you want to have the library installed in some
+    other directory than
+    <emphasis>PREFIX</emphasis><literal>/lib/</literal>.</para>
+  </listitem>
+  <listitem>
+    <para><literal>--includedir=</literal><emphasis>INCLUDEDIR</emphasis>:
+    Use this option in case you want to have the header files
+    installed in some other directory than
+    <emphasis>PREFIX</emphasis><literal>/include/GiNaC/</literal>. For
+    instance, if you specify
+    <literal>--includedir=/usr/include</literal> you will end up with
+    the header files sitting in the directory
+    <literal>/usr/include/GiNaC/</literal>. Note that the subdirectory
+    <literal>GiNaC</literal> is enforced by this process in order to
+    keep the header files separated from others.  This avoids some
+    clashes and allows for an easier deinstallation of GiNaC. This ought
+    to be considered A Good Thing (tm).</para>
+  </listitem>
+  <listitem>
+    <para><literal>--datadir=</literal><emphasis>DATADIR</emphasis>:
+    This option may be given in case you want to have the documentation 
+    installed in some other directory than
+    <emphasis>PREFIX</emphasis><literal>/share/doc/GiNaC/</literal>.
+  </listitem>
+</itemizedlist>
+</para>
+
+<para>In addition, you may specify some environment variables.
+<literal>CXX</literal> holds the path and the name of the C++ compiler
+in case you want to override the default in your path.  (The
+<literal>configure</literal> script searches your path for
+<literal>c++</literal>, <literal>g++</literal>,
+<literal>gcc</literal>, <literal>CC</literal>, <literal>cxx</literal>
+and <literal>cc++</literal> in that order.)  It may be very useful to
+define some compiler flags with the <literal>CXXFLAGS</literal>
+environment variable, like optimization, debugging information and
+warning levels.  If ommitted, it defaults to <literal>-g
+-O2</literal>.</para>
+
+<para>The whole process is illustrated in the following two
+examples. (Substitute <literal>setenv VARIABLE value</literal> for
+<literal>export VARIABLE=value</literal> if the Berkeley C shell is
+your login shell.)
+
+<example><title>Sample sessions of how to call the
+configure-script</title> <para>Simple configuration for a site-wide
+GiNaC library assuming everything is in default paths:</para>
+<screen>
+<prompt>sysprompt></prompt> export CXXFLAGS="-Wall -O2"
+<prompt>sysprompt></prompt> ./configure --enable-shared
+</screen>
+<para>Configuration for a private GiNaC library with several
+components sitting in custom places (site-wide <literal>GCC</literal>
+and private <literal>CLN</literal>):</para>
+<screen>
+<prompt>sysprompt></prompt> export CXX=/usr/local/gnu/bin/c++
+<prompt>sysprompt></prompt> export CPPFLAGS="${CPPFLAGS} -I${HOME}/include"
+<prompt>sysprompt></prompt> export CXXFLAGS="${CXXFLAGS} -ggdb -Wall -ansi -pedantic -O2"
+<prompt>sysprompt></prompt> export LDFLAGS="${LDFLAGS} -L${HOME}/lib"
+<prompt>sysprompt></prompt> ./configure --enable-shared --prefix=${HOME}
+</screen>
+</example>
+</para>
+
+</sect1>
+
+<sect1><title>Building GiNaC</title>
+
+<para>After proper configuration you should just build the whole
+library by typing <literal>make</literal> at the command
+prompt and go for a cup of coffee.</para>
+
+<para>Just to make sure GiNaC works properly you may run a simple test
+suite by typing <literal>make check</literal>.  This will compile some
+sample programs, run them and compare the output to reference output.
+Each of the checks should return a message <literal>passed</literal>
+together with the CPU time used for that particular test.  If it does
+not, something went wrong.  This is mostly intended to be a check if
+something was broken during the development, but not a sanity check of
+your system.  Another intent is to allow people to fiddle around with
+optimization.  If <literal>CLN</literal> was installed all right this
+step is unlikely to return any errors.</para>
+
+</sect1>
+
+<sect1><title>Installation</title>
+
+<para>To install GiNaC on your system, simply type <literal>make
+install</literal>.  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):
+<itemizedlist>
+  <listitem>
+    <para><literal>libginac.a</literal> will go into
+    <emphasis>PREFIX</emphasis><literal>/lib/</literal> (or
+    <emphasis>LIBDIR</emphasis>) which defaults to
+    <literal>/usr/local/lib/</literal>.  So will
+    <literal>libginac.so</literal> if the the configure script was
+    given the option <literal>--enable-shared</literal>.  In that
+    case, the proper symlinks will be established as well (by running
+    <literal>ldconfig</literal>).</para>
+  </listitem>
+  <listitem>
+    <para>All the header files will be installed into
+    <emphasis>PREFIX</emphasis><literal>/include/GiNaC/</literal> (or
+    <emphasis>INCLUDEDIR</emphasis><literal>/GiNaC/</literal>, if
+    specified).</para>
+  </listitem>
+  <listitem>
+    <para>All documentation (HTML, Postscript and DVI) will be stuffed
+    into
+    <emphasis>PREFIX</emphasis><literal>/share/doc/GiNaC/</literal>
+    (or <emphasis>DATADIR</emphasis><literal>/doc/GiNaC/</literal>, if
+    specified).</para>
+  </listitem>
+</itemizedlist>
+</para>
+
+<para>Just for the record we will list some other useful make targets:
+<literal>make clean</literal> deletes all files generated by
+<literal>make</literal>, i.e. all the object files.  In addition
+<literal>make distclean</literal> removes all files generated by
+configuration.  And finally <literal>make uninstall</literal> removes
+the installed library and header files<footnoteref
+linkend="warnuninstall-1">.  
+
+  <footnote id="warnuninstall-1"><para>Uninstallation does not work
+  after you have called <literal>make distclean</literal> since the
+  <literal>Makefile</literal> is itself generated by the configuration
+  from <literal>Makefile.in</literal> and hence deleted by
+  <literal>make distclean</literal>.  There are two obvious ways out
+  of this dilemma.  First, you can run the configuration again with
+  the same <emphasis>PREFIX</emphasis> thus creating a
+  <literal>Makefile</literal> with a working
+  <literal>uninstall</literal> target.  Second, you can do it by hand
+  since you now know where all the files went during
+  installation.</para></footnote>
+</para>
+
+</sect1>
+</chapter>
+
+
+<chapter>
+<title>Basic Concepts</title>
+
+<para>This chapter will describe the different fundamental objects
+that can be handled with 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.</para>
+
+<sect1><title>Expressions</title>
+
+<para>The most common class of objects a user deals with is the
+expression <literal>ex</literal>, 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:
+<example><title>Examples of expressions</title>
+<programlisting>
+    ex MyEx1 = 5;                       // simple number
+    ex MyEx2 = x + 2*y;                 // polynomial in x and y
+    ex MyEx3 = (x + 1)/(x - 1);         // rational expression
+    ex MyEx4 = sin(x + 2*y) + 3*z + 41; // containing a function
+    ex MyEx5 = MyEx4 + 1;               // similar to above
+</programlisting>
+</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.</para>
+
+<sect2><title>Digression: Expressions are reference counted</title>
+
+<para>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 <literal>ex</literal> 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><title>Simple copy-on-write semantics</title>
+<programlisting>
+#include &lt;GiNaC/ginac.h&gt;
+
+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 &lt;&lt; e2 &lt;&lt; endl;     // prints sin(x+2*y)+3*z+41
+    e2 += 1;                // e2 is copied into a new object
+    cout &lt;&lt; e2 &lt;&lt; endl;     // prints sin(x+2*y)+3*z+42
+    // ...
+}
+</programlisting>
+</example>
+The line <literal>e2 = e1;</literal> creates a second expression
+pointing to the object held already by <literal>e1</literal>.  The
+time involved for this operation is therefore constant, no matter how
+large <literal>e1</literal> was.  Actual copying, however, must take
+place in the line <literal>e2 += 1</literal> because
+<literal>e1</literal> and <literal>e2</literal> are not handles for
+the same object any more.  This concept is called
+<emphasis>copy-on-write semantics</emphasis>.  It increases
+performance considerably whenever one object occurs multiple times and
+represents a simple garbage collection scheme because when an
+<literal>ex</literal> 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><title>Advanced
+copy-on-write semantics</title>
+<programlisting>
+#include &lt;GiNaC/ginac.h&gt;
+
+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 &lt;&lt; e1 &lt;&lt; endl          // prints x+3*y
+         &lt;&lt; e2 &lt;&lt; endl          // prints (x+3*y)^3
+         &lt;&lt; e3 &lt;&lt; endl;         // prints 3*(x+3*y)^2*cos((x+3*y)^3)
+    // ...
+}
+</programlisting>
+</example>
+Here, <literal>e1</literal> will actually be referenced three times
+while <literal>e2</literal> 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
+<literal>e1</literal> is involved when <literal>e3</literal> is
+constructed.  So, when <literal>e3</literal> is constructed it will
+print as <literal>3*(x+3*y)^2*cos((x+3*y)^3)</literal> but the
+argument of <literal>cos()</literal> only holds a reference to
+<literal>e2</literal> and the factor in front is just
+<literal>3*e1^2</literal>.
+</para>
+
+<para>As a user of GiNaC, you cannot see this mechanism of
+copy-on-write semantics.  When you insert an expression into a
+second expression, the result behaves exactly as if the contents of
+the first expression were inserted.  But it may be useful to remember
+that this is not what happens.  Knowing this will enable you to write
+much more efficient code.</para>
+
+<para>So much for expressions.  But what exactly are these expressions
+handles of?  This will be answered in the following sections.</para>
+</sect2>
+</sect1>
+
+<sect1><title>The Class Hierarchy</title>
+
+<para>GiNaC's class hierarchy consists of several classes representing
+mathematical objects, all of which (except for <literal>ex</literal>
+and some helpers) are internally derived from one abstract base class
+called <literal>basic</literal>.  You do not have to deal with objects
+of class <literal>basic</literal>, 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.</para>
+
+<para>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.
+<figure id="classhier-id" float="1">
+<title>The GiNaC class hierarchy</title>
+  <graphic align="center" fileref="classhierarchy.graext" format="GRAEXT"></graphic>
+</figure>
+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 <literal>expairseq</literal>, which is a container
+for a sequence of pairs each consisting of one expression and a number
+(<literal>numeric</literal>).  What <emphasis>is</emphasis> visible to
+the user are the derived classes <literal>add</literal> and
+<literal>mul</literal>, 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.</para>
+
+<sect2><title>Digression: Internal representation of products and sums</title>
+
+<para>Although it should be completely transparent for the user of
+GiNaC a short discussion of this topic helps understanding the sources
+and also explains performance to a large degree.  Consider the
+symbolic expression <literal>(a+2*b-c)*d</literal>, which could
+naively be represented by a tree of linear containers for addition and
+multiplication together with atomic leaves of symbols and integer
+numbers in this fashion:
+<figure id="repres-naive-id" float="1">
+<title>Naive internal representation of <emphasis>d(a+2*b-c)</emphasis></title>
+  <graphic align="center" fileref="rep_naive.graext" format="GRAEXT"></graphic>
+</figure>
+However, doing so results in a rather deeply nested tree which will
+quickly become rather slow to manipulate.  If we represent the sum
+instead as a sequence of terms, each having a purely numeric
+coefficient, the tree becomes much more flat.
+<figure id="repres-pair-id" float="1">
+<title>Better internal representation of <emphasis>d(a+2*b-c)</emphasis></title>
+  <graphic align="center" fileref="rep_pair.graext" format="GRAEXT"></graphic>
+</figure>
+The number <literal>1</literal> under the symbol <literal>d</literal>
+is a hint that multiplication objects can be treated similarly where
+the coeffiecients are interpreted as <emphasis>exponents</emphasis>
+now.  Addition of sums of terms or multiplication of products with
+numerical exponents can be made very efficient with a
+pair-representation.  Internally, this handling is done by most CAS in
+this way.  It typically speeds up manipulations by an order of
+magnitude.  Now it should be clear, why both classes
+<literal>add</literal> and <literal>mul</literal> are derived from the
+same abstract class: the representation is the same, only the
+interpretation differs.  </para>
+
+</sect1>
+
+<sect1><title>Symbols</title>
+
+<para>Symbols are for symbolic manipulation what atoms are for
+chemistry.  You can declare objects of type symbol as any other object
+simply by saying <literal>symbol x,y;</literal>.  There is, however, a
+catch in here having to do with the fact that C++ is a compiled
+language.  The information about the symbol's name is thrown away by
+the compiler but at a later stage you may want to print expressions
+holding your symbols.  In order to avoid confusion GiNaC's symbols are
+able to know their own name.  This is accompilshed by declaring its
+name for output at construction time in the fashion <literal>symbol
+x("x");</literal>.</para>
+
+<para>Although symbols can be assigned expressions for internal
+reasons, you should not do it (and we are not going to tell you how it
+is done).  If you want to replace a symbol with something else in an
+expression, you can use the expression's <literal>.subs()</literal>
+method.</para>
+
+</sect1>
+
+<sect1><title>Numbers</title>
+
+<para>For storing numerical things, GiNaC uses Bruno Haible's library
+<literal>CLN</literal>.  The classes therein serve as foundation
+classes for GiNaC.  <literal>CLN</literal> stands for Class Library
+for Numbers or alternatively for Common Lisp Numbers.  In order to
+find out more about <literal>CLN</literal>'s internals the reader is
+refered to the documentation of that library.  Suffice to say that it
+is by itself build on top of another library, the GNU Multiple
+Precision library <literal>GMP</literal>, which is a extremely fast
+library for arbitrary long integers and rationals as well as arbitrary
+precision floating point numbers.  It is very commonly used by several
+popular cryptographic applications.  <literal>CLN</literal> extends
+<literal>GMP</literal> 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.</para>
+
+<para>The user can construct an object of class
+<literal>numeric</literal> 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.
+<example><title>Sample C++ program</title>
+<programlisting>
+#include &lt;GiNaC/ginac.h&gt;
+
+int main()
+{
+    numeric two(2);                     // exact integer 2
+    numeric r(2,3);                     // exact fraction 2/3
+    numeric e(2.71828);                 // floating point number
+    numeric p("3.1415926535897932385"); // floating point number
+
+    cout &lt;&lt; two*p &lt;&lt; endl;  // floating point 6.283...
+    // ...
+}
+</programlisting>
+</example>
+Note that all those constructors are <emphasis>explicit</emphasis>
+which means you are not allowed to write <literal>numeric
+two=2;</literal>.  This is because the basic objects to be handled by
+GiNaC are the expressions and we want to keep things simple and wish
+objects like <literal>pow(x,2)</literal> to be handled the same way
+as <literal>pow(x,a)</literal>, which means that we need to allow a
+general expression as base and exponent.  Therefore there is an
+implicit construction from a C-integer directly to an expression
+handling a numeric in the first example.  This design really becomes
+convenient when one declares own functions having more than one
+parameter but it forbids using implicit constructors because that
+would lead to ambiguities.
+</para>
+
+<para>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 <emphasis>global</emphasis> variable, called
+<literal>Digits</literal>.  (For those readers who know about Maple:
+it behaves very much like Maple's <literal>Digits</literal>).  All
+objects of class numeric that are constructed from then on will be
+stored with a precision matching that number of decimal digits:
+<example><title>Controlling the precision of floating point numbers</title>
+<programlisting> 
+#include
+&lt;GiNaC/ginac.h&gt;
+
+void foo()
+{
+    numeric three(3.0), one(1.0);
+    numeric x = one/three;
+
+    cout &lt;&lt; "in " &lt;&lt; Digits &lt;&lt; " digits:" &lt;&lt; endl;
+    cout &lt;&lt; x &lt;&lt; endl;
+    cout &lt;&lt; Pi.evalf() &lt;&lt; endl;
+}
+
+int main()
+{
+    foo();
+    Digits = 60;
+    foo();
+    return 0;
+}
+</programlisting>
+</example>
+The above example prints the following output to screen:
+<screen>
+in 17 digits:
+0.333333333333333333
+3.14159265358979324
+in 60 digits:
+0.333333333333333333333333333333333333333333333333333333333333333333
+3.14159265358979323846264338327950288419716939937510582097494459231
+</screen>
+</para>
+
+<sect2><title>Tests on numbers</title>
+
+<para>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.)</para>
+
+<para>As an example, let's construct some rational number, multiply it
+with some multiple of its denominator and check what comes out:
+<example><title>Sample test on objects of type numeric</title>
+<programlisting>
+#include &lt;GiNaC/ginac.h&gt;
+
+int main()
+{
+    numeric twentyone(21);
+    numeric ten(10);
+    numeric answer(21,5);
+
+    cout &lt;&lt; answer.is_integer() &lt;&lt; endl;  // false, it's 21/5
+    answer *= ten;
+    cout &lt;&lt; answer.is_integer() &lt;&lt; endl;  // true, it's 42 now!
+    // ...
+}
+</programlisting>
+</example>
+Note that the variable <literal>answer</literal> is constructed here
+as an integer but in an intermediate step it holds a rational number
+represented as integer numerator and denominator.  When multiplied by
+10, the denominator becomes unity and the result is automatically
+converted to a pure integer again.  Internally, the underlying
+<literal>CLN</literal> is responsible for this behaviour and we refer
+the reader to <literal>CLN</literal>'s documentation.  Suffice to say
+that the same behaviour applies to complex numbers as well as return
+values of certain functions.  Complex numbers are automatically
+converted to real numbers if the imaginary part becomes zero.  The
+full set of tests that can be applied is listed in the following
+table.
+<informaltable colsep="0" frame="topbot" pgwide="1">
+<tgroup cols="2">
+<colspec colnum="1" colwidth="1*">
+<colspec colnum="2" colwidth="2*">
+<thead>
+  <row>
+    <entry>Method</entry>
+    <entry>Returns true if...</entry>
+  </row>
+</thead>
+<tbody>
+  <row>
+    <entry><literal>.is_zero()</literal></entry>
+    <entry>object is equal to zero</entry>
+  </row>
+  <row>
+    <entry><literal>.is_positive()</literal></entry>
+    <entry>object is not complex and greater than 0</entry>
+  </row>
+  <row>
+    <entry><literal>.is_integer()</literal></entry>
+    <entry>object is a (non-complex) integer</entry>
+  </row>
+  <row>
+    <entry><literal>.is_pos_integer()</literal></entry>
+    <entry>object is an integer and greater than 0</entry>
+  </row>
+  <row>
+    <entry><literal>.is_nonneg_integer()</literal></entry>
+    <entry>object is an integer and greater equal 0</entry>
+  </row>
+  <row>
+    <entry><literal>.is_even()</literal></entry>
+    <entry>object is an even integer</entry>
+  </row>
+  <row>
+    <entry><literal>.is_odd()</literal></entry>
+    <entry>object is an odd integer</entry>
+  </row>
+  <row>
+    <entry><literal>.is_prime()</literal></entry>
+    <entry>object is a prime integer (probabilistic primality test)</entry>
+  </row>
+  <row>
+    <entry><literal>.is_rational()</literal></entry>
+    <entry>object is an exact rational number (integers are rational, too, as are complex extensions like <literal>2/3+7/2*I</literal>)</entry>
+  </row>
+  <row>
+    <entry><literal>.is_real()</literal></entry>
+    <entry>object is a real integer, rational or float (i.e. is not complex)</entry>
+  </row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+
+</sect2>
+
+</sect1>
+
+
+<sect1><title>Constants</title>
+
+<para>Constants behave pretty much like symbols except that that they return
+some specific number when the method <literal>.evalf()</literal> is called.
+</para>
+
+<para>The predefined known constants are:
+<informaltable colsep="0" frame="topbot" pgwide="1">
+<tgroup cols="3">
+<colspec colnum="1" colwidth="1*">
+<colspec colnum="2" colwidth="2*">
+<colspec colnum="3" colwidth="4*">
+<thead>
+  <row>
+    <entry>Name</entry>
+    <entry>Common Name</entry>
+    <entry>Numerical Value (35 digits)</entry>
+  </row>
+</thead>
+<tbody>
+  <row>
+    <entry><literal>Pi</literal></entry>
+    <entry>Archimedes' constant</entry>
+    <entry>3.14159265358979323846264338327950288</entry>
+  </row><row>
+    <entry><literal>Catalan</literal></entry>
+    <entry>Catalan's constant</entry>
+    <entry>0.91596559417721901505460351493238411</entry>
+  </row><row>
+    <entry><literal>EulerGamma</literal></entry>
+    <entry>Euler's (or Euler-Mascheroni) constant</entry>
+    <entry>0.57721566490153286060651209008240243</entry>
+  </row>
+</tbody>
+</tgroup>
+</informaltable>
+</para>
+
+</sect1>
+
+<sect1><title>Fundamental operations: The <literal>power</literal>, <literal>add</literal> and <literal>mul</literal> classes</title>
+
+<para>Simple polynomial expressions are written down in GiNaC pretty
+much like in other CAS.  The necessary operators <literal>+</literal>,
+<literal>-</literal>, <literal>*</literal> and <literal>/</literal>
+have been overloaded to achieve this goal.  When you run the following
+program, the constructor for an object of type <literal>mul</literal>
+is automatically called to hold the product of <literal>a</literal>
+and <literal>b</literal> and then the constructor for an object of
+type <literal>add</literal> is called to hold the sum of that
+<literal>mul</literal> object and the number one:
+<example><title>Construction of <literal>add</literal> and <literal>mul</literal> objects</title>
+<programlisting>
+#include &lt;GiNaC/ginac.h&gt;
+
+int main()
+{
+    symbol a("a"), b("b");
+    ex MyTerm = 1+a*b;
+    // ...
+}
+</programlisting>
+</example></para>
+
+<para>For exponentiation, you have already seen the somewhat clumsy
+(though C-ish) statement <literal>pow(x,2);</literal> to represent
+<literal>x</literal> squared.  This direct construction is necessary
+since we cannot safely overload the constructor <literal>^</literal>
+in <literal>C++</literal> to construct a <literal>power</literal>
+object.  If we did, it would have two counterintuitive effects:
+<itemizedlist>
+  <listitem>
+    <para>Due to <literal>C</literal>'s operator precedence,
+    <literal>2*x^2</literal> would be parsed as <literal>(2*x)^2</literal>.
+  </listitem>
+  <listitem>
+    <para>Due to the binding of the operator <literal>^</literal>, 
+    <literal>x^2^3</literal> would result in <literal>x^8</literal>. 
+    This would be confusing since most (though not all) other CAS 
+    interpret this as <literal>x^6</literal>.</para>
+  </listitem>
+</itemizedlist>
+Both effects are contrary to mathematical notation and differ from the
+way most other CAS handle exponentiation, therefore overloading
+<literal>^</literal> is ruled out.  (Also note, that the other
+frequently used exponentiation operator <literal>**</literal> does not
+exist at all in <literal>C++</literal>).</para>
+
+<para>To be somewhat more precise, objects of the three classes
+described here, are all containers for other expressions.  An object
+of class <literal>power</literal> 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 <literal>pow(pow(x,2),3)</literal> to
+<literal>x^6</literal> automatically are only performed when
+this is mathematically possible.  If we replace the outer exponent
+three in the example by some symbols <literal>a</literal>, the
+simplification is not safe and will not be performed, since
+<literal>a</literal> might be <literal>1/2</literal> and
+<literal>x</literal> negative.</para>
+
+<para>Objects of type <literal>add</literal> and
+<literal>mul</literal> are containers with an arbitrary number of
+slots for expressions to be inserted.  Again, simple and safe
+simplifications are carried out like transforming
+<literal>3*x+4-x</literal> to <literal>2*x+4</literal>.</para>
+
+<para>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 <literal>a-a</literal> 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.</para>
+
+</sect1>
+
+<sect1><title>Built-in Functions</title>
+
+<para>This chapter is not here yet</para>
+
+
+
+</sect1>
+
+</chapter>
+
+
+<chapter>
+<title>Important Algorithms</title>
+
+<para>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:
+<example><title>Methods vs. wrapper functions</title>
+<programlisting>
+#include &lt;GiNaC/ginac.h&gt;
+
+int main()
+{
+    ex x = numeric(1.0);
+    
+    cout &lt;&lt; "As method:   " &lt;&lt; sin(x).evalf() &lt;&lt; endl;
+    cout &lt;&lt; "As function: " &lt;&lt; evalf(sin(x)) &lt;&lt; endl;
+    // ...
+}
+</programlisting>
+</example>
+The general rule is that wherever methods accept one or more
+parameters (<emphasis>arg1</emphasis>, <emphasis>arg2</emphasis>, ...)
+the order of arguments the function wrapper accepts is the same but
+preceded by the object to act on (<emphasis>object</emphasis>,
+<emphasis>arg1</emphasis>, <emphasis>arg2</emphasis>, ...).  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
+<literal>A:=x+1; subs(x=2,A);</literal> GiNaC would require
+<literal>A=x+1; subs(A,x==2);</literal> (after proper declaration of A
+and x).  On the other hand, since MapleV returns 3 on
+<literal>A:=x^2+3; coeff(A,x,0);</literal> (GiNaC:
+<literal>A=pow(x,2)+3; coeff(A,x,0);</literal>) 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 <literal>ex</literal> and sometimes calling a function cannot be
+avoided.
+</para>
+
+<sect1><title>Polynomial Expansion</title>
+
+<para>A polynomial in one or more variables has many equivalent
+representations.  Some useful ones serve a specific purpose.  Consider
+for example the trivariate polynomial <literal>4*x*y + x*z + 20*y^2 +
+21*y*z + 4*z^2</literal>.  It is equivalent to the factorized
+polynomial <literal>(x + 5*y + 4*z)*(4*y + z)</literal>.  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
+<literal>(4*y + z)*x + 20*y^2 + 21*y*z + 4*z^2</literal> and
+<literal>20*y^2 + (21*z + 4*x)*y + 4*z^2 + x*z</literal>.
+</para>
+
+<para>To bring an expression into expanded form, its method
+<function>.expand()</function> may be called.  In our example above,
+this corresponds to <literal>4*x*y + x*z + 20*y^2 + 21*y*z +
+4*z^2</literal>.  There is no canonical form in GiNaC.  Be prepared to
+see different orderings of terms in such sums!  </para>
+
+</sect1>
+
+<sect1><title>Collecting expressions</title>
+
+<para>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
+<literal>collect()</literal> accomplishes this task:
+<funcsynopsis>
+  <funcsynopsisinfo>#include &lt;GiNaC/ginac.h></funcsynopsisinfo>
+  <funcdef>ex <function>ex::collect</function></funcdef>
+  <paramdef>symbol const & <parameter>s</parameter></paramdef>
+</funcsynopsis>
+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
+<funcsynopsis>
+  <funcsynopsisinfo>#include &lt;GiNaC/ginac.h></funcsynopsisinfo>
+  <funcdef>int <function>ex::degree</function></funcdef>
+  <paramdef>symbol const & <parameter>s</parameter></paramdef>
+</funcsynopsis>
+<funcsynopsis>
+  <funcdef>int <function>ex::ldegree</function></funcdef>
+  <paramdef>symbol const & <parameter>s</parameter></paramdef>
+</funcsynopsis>
+where <literal>degree()</literal> returns the highest coefficient and
+<literal>ldegree()</literal> the lowest one.  These two methods work
+also reliably on non-expanded input polynomials.  This is illustrated
+in the following example: 
+
+<example><title>Collecting expressions in multivariate polynomials</title>
+<programlisting>
+#include &lt;GiNaC/ginac.h&gt;
+
+int main()
+{
+    symbol x("x"), y("y");
+    ex PolyInp = 4*pow(x,3)*y + 5*x*pow(y,2) + 3*y
+                 - pow(x+y,2) + 2*pow(y+2,2) - 8;
+    ex Poly = PolyInp.expand();
+    
+    for (int i=Poly.ldegree(x); i<=Poly.degree(x); ++i) {
+        cout &lt;&lt; "The x^" &lt;&lt; i &lt;&lt; "-coefficient is "
+             &lt;&lt; Poly.coeff(x,i) &lt;&lt; endl;
+    }
+    cout &lt;&lt; "As polynomial in y: " 
+         &lt;&lt; Poly.collect(y) &lt;&lt; endl;
+    // ...
+}
+</programlisting>
+</example>
+When run, it returns an output in the following fashion:
+<screen>
+The x^0-coefficient is y^2+11*y
+The x^1-coefficient is 5*y^2-2*y
+The x^2-coefficient is -1
+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
+</screen>
+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.</para>
+
+</sect1>
+
+<sect1 id="gcd-main"><title>Polynomial Arithmetic</title>
+
+<sect2><title>GCD and LCM</title>
+
+<para>The functions for polynomial greatest common divisor and least common
+multiple have the synopsis:
+<funcsynopsis>
+  <funcsynopsisinfo>#include &lt;GiNaC/normal.h></funcsynopsisinfo>
+  <funcdef>ex <function>gcd</function></funcdef>
+  <paramdef>const ex *<parameter>a</parameter>, const ex *<parameter>b</parameter></paramdef>
+</funcsynopsis>
+<funcsynopsis>
+  <funcdef>ex <function>lcm</function></funcdef>
+  <paramdef>const ex *<parameter>a</parameter>, const ex *<parameter>b</parameter></paramdef>
+</funcsynopsis></para>
+
+<para>The functions <function>gcd()</function> and <function
+id="lcm-main">lcm()</function> accepts two expressions
+<literal>a</literal> and <literal>b</literal> as arguments and return
+a new expression, their greatest common divisor or least common
+multiple, respectively.  If the polynomials <literal>a</literal> and
+<literal>b</literal> are coprime <function>gcd(a,b)</function> returns 1
+and <function>lcm(a,b)</function> returns the product of
+<literal>a</literal> and <literal>b</literal>.
+<example><title>Polynomal GCD/LCM</title>
+<programlisting>
+#include &lt;GiNaC/ginac.h&gt;
+
+int main()
+{
+    symbol x("x"), y("y"), z("z");
+    ex P_a = 4*x*y + x*z + 20*pow(y, 2) + 21*y*z + 4*pow(z, 2);
+    ex P_b = x*y + 3*x*z + 5*pow(y, 2) + 19*y*z + 12*pow(z, 2);
+
+    ex P_gcd = gcd(P_a, P_b);
+    // x + 5*y + 4*z
+    ex P_lcm = lcm(P_a, P_b);
+    // 4*x*y^2 + 13*y*x*z + 20*y^3 + 81*y^2*z + 67*y*z^2 + 3*x*z^2 + 12*z^3
+    // ...
+}
+</programlisting>
+</example>
+</para>
+
+</sect2>
+
+<sect2><title>The <function>normal</function> method</title>
+
+<para>While in common symbolic code <function>gcd()</function> and
+<function>lcm()</function> are not too heavily used, some basic
+simplification occurs frequently.  Therefore
+<function>.normal()</function>, which provides some basic form of
+simplification, has become a method of class <literal>ex</literal>,
+just like <literal>.expand()</literal>.</para>
+
+</sect2>
+
+</sect1>
+
+<sect1><title>Symbolic Differentiation</title>
+
+<para>
+<example><title>Simple polynomial differentiation</title>
+<programlisting>
+#include &lt;GiNaC/ginac.h&gt;
+
+int main()
+{
+    symbol x("x"), y("y"), z("z");
+    ex P = pow(x, 5) + pow(x, 2) + y;
+
+    cout &lt;&lt; P.diff(x,2) &lt;&lt; endl;  // 20*x^3 + 2
+    cout &lt;&lt; P.diff(y) &lt;&lt; endl;    // 1
+    cout &lt;&lt; P.diff(z) &lt;&lt; endl;    // 0
+    // ...
+}
+</programlisting>
+</example>
+</para>
+
+<para>
+<example><title>Differentiation with nontrivial functions</title>
+<programlisting>
+#include &lt;GiNaC/ginac.h&gt;
+
+int main()
+{
+    // To Be Done...
+}
+</programlisting>
+</example>
+</para>
+
+</sect1>
+
+<sect1><title>Series Expansion</title>
+
+<para>Expressions know how to expand themselfes as a Taylor series or
+(more generally) a Laurent series.  As in most conventional Computer
+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:
+<example><title>Series expansion</title>
+<programlisting>
+#include &lt;GiNaC/ginac.h&gt;
+
+int main()
+{
+    symbol x("x");
+    numeric point(0);
+    ex MyExpr1 = sin(x);
+    ex MyExpr2 = 1/(x - pow(x, 2) - pow(x, 3));
+    ex MyTailor, MySeries;
+    
+    MyTailor = MyExpr1.series(x, numZERO(), 5);
+    cout &lt;&lt; MyExpr1 &lt;&lt; " == " &lt;&lt; MyTailor
+         &lt;&lt; " for small " &lt;&lt; x &lt;&lt; endl;
+    MySeries = MyExpr2.series(x, numZERO(), 7);
+    cout &lt;&lt; MyExpr2 &lt;&lt; " == " &lt;&lt; MySeries
+         &lt;&lt; " for small " &lt;&lt; x &lt;&lt; endl;
+    \\ ...
+}
+</programlisting>
+</example>
+</para>
+
+</sect1>
+
+</chapter>
+
+
+<chapter>
+<title>Extending GiNaC</title>
+
+<para>Longish chapter follows here.</para>
+
+</chapter>
+
+
+<chapter>
+<title>A Comparison with other CAS</title>
+
+<para>This chapter will give you some information on how GiNaC
+compares to other, traditional Computer Algebra Systems, like
+<literal>Maple</literal>, <literal>Mathematica</literal> or
+<literal>Reduce</literal>, where it has advantages and disadvantages
+over these systems.</para>
+
+<sect1><title>Advantages</title>
+
+<para>GiNaC has several advantages over traditional Computer
+Algebra Systems, like 
+
+<itemizedlist>
+  <listitem>
+    <para>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 <literal>C++</literal>, which is
+    standardized.</para>
+  </listitem>
+  <listitem>
+    <para>structured data types: you can build up structured data
+    types using <literal>struct</literal>s or <literal>class</literal>es
+    together with STL features instead of using unnamed lists of lists
+    of lists.</para>
+  </listitem>
+  <listitem>
+    <para>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.
+    </para>
+  </listitem>
+  <listitem>
+    <para>development tools: powerful development tools exist for
+    <literal>C++</literal>, like fancy editors (e.g. with automatic
+    indentation and syntax highlighting), debuggers, visualization
+    tools, documentation tools...</para>
+  </listitem>
+  <listitem>
+    <para>modularization: <literal>C++</literal> programs can 
+    easily be split into modules by separating interface and
+    implementation.</para>
+  </listitem>
+  <listitem>
+    <para>price: GiNaC is distributed under the GNU Public License
+    which means that it is free and available with source code.  And
+    there are excellent <literal>C++</literal>-compilers for free, too.
+    </para>
+  </listitem>
+  <listitem>
+    <para>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.
+  </listitem>
+  <listitem>
+    <para>seemless integration: it is somewhere between difficult
+    and impossible to call CAS functions from within a program 
+    written in <literal>C++</literal> 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. <literal>Maple</literal>) to providing a
+    method for "embedding" the system
+    (i.e. <literal>Yacas</literal>).</para>
+  </listitem>
+  <listitem>
+    <para>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.
+  </listitem>
+</itemizedlist>
+</para>
+
+<sect1><title>Disadvantages</title>
+
+<para>Of course it also has some disadvantages
+
+<itemizedlist>
+  <listitem>
+    <para>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 <literal>CINT</literal>
+    <literal>C++</literal> interpreter.</para>
+  </listitem>
+  <listitem>
+    <para>advanced features: GiNaC cannot compete with a program
+    like <literal>Reduce</literal> which exists for more than
+    30 years now or <literal>Maple</literal> 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).</para>
+  </listitem>
+  <listitem>
+    <para>portability: While the GiNaC library itself is designed
+    to avoid any platform dependent features (it should compile
+    on any ANSI compliant <literal>C++</literal> 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 <literal>C++</literal> compiler from the
+    GNU Compiler Collection (<literal>GCC</literal>).  GiNaC uses
+    recent language features like explicit constructors, mutable
+    members, RTTI, dynamic_casts and STL, so ANSI compliance is meant
+    literally.  Recent <literal>GCC</literal> versions starting at
+    2.95, although itself not yet ANSI compliant, support all needed
+    features.
+    </para>
+  </listitem>
+</itemizedlist>
+</para>
+
+<sect1><title>Why <literal>C++</literal>?</title>
+
+<para>Why did we choose to implement GiNaC in <literal>C++</literal>
+instead of <literal>Java</literal> or any other language?
+<literal>C++</literal> 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
+<literal>C++</literal>. While it may be true that operating on classes
+with a <literal>+</literal> operator is rarely meaningful, it is
+perfectly suited for algebraic expressions. Writing 3x+5y as
+<literal>3*x+5*y</literal> instead of
+<literal>x.times(3).plus(y.times(5))</literal> looks much more
+natural. Furthermore, the main developers are more familiar with
+<literal>C++</literal> than with any other programming
+language.</para>
+
+</chapter>
+
+
+<bibliography>
+<bibliodiv>
+
+<biblioentry>
+  <bookbiblio>
+    <title>ISO/IEC 14882:1998</title>
+    <subtitle>Programming Languages: C++</subtitle>
+  </bookbiblio>
+</biblioentry>
+
+<bibliomixed>
+  <title>CLN: A Class Library for Numbers</title>
+  <authorgroup>
+    <author>
+      <firstname>Bruno</firstname><surname>Haible</surname>
+      <affiliation><address><email>haible@ilog.fr</email></address></affiliation>
+    </author>
+  </authorgroup>
+</bibliomixed>
+
+<biblioentry>
+  <bookbiblio>
+    <title>The C++ Programming Language</title>
+    <authorgroup><author><firstname>Bjarne</firstname><surname>Stroustrup</surname></author></authorgroup>
+    <edition>3</edition>
+    <isbn>0-201-88954-4</isbn>
+    <publisher><publishername>Addison Wesley</publishername></publisher>
+  </bookbiblio>
+</biblioentry>
+
+<biblioentry>
+  <bookbiblio>
+    <title>Algorithms for Computer Algebra</title>
+    <authorgroup>
+      <author><firstname>Keith</firstname><othername>O.</othername><surname>Geddes</surname></author>
+      <author><firstname>Stephen</firstname><othername>R.</othername><surname>Czapor</surname></author>
+      <author><firstname>George</firstname><surname>Labahn</surname></author>
+    </authorgroup>
+    <isbn>0-7923-9259-0</isbn>
+    <pubdate>1992</pubdate>
+    <publisher>
+      <publishername>Kluwer Academic Publishers</publishername>
+      <address><city>Norwell</city>, <state>Massachusetts</state></address>
+    </publisher>
+  </bookbiblio>
+</biblioentry>
+
+<biblioentry>
+  <bookbiblio>
+    <title>Computer Algebra</title>
+    <subtitle>Systems and Algorithms for Algebraic Computation</subtitle>
+    <authorgroup>
+      <author><firstname>J.</firstname><othername>H.</othername><surname>Davenport</surname></author>
+      <author><firstname>Y.</firstname><surname>Siret</surname></author>
+      <author><firstname>E.</firstname><surname>Tournier</surname></author>
+    </authorgroup>
+    <isbn>0-12-204230-1</isbn>
+    <pubdate>1988</pubdate>
+    <publisher>
+      <publishername>Academic Press</publishername>
+      <address><city>London</city></address>
+    </publisher>
+  </bookbiblio>
+</biblioentry>
+
+</bibliodiv>
+</bibliography>
+
+
+<index id="index">
+<title>Index</title>
+
+<indexentry>
+  <primaryie linkends="CLN-main">CLN</primaryie>
+  <secondaryie linkends="ind123">obtaining</secondaryie>
+</indexentry>
+
+<indexentry id="ind-gcd">
+  <primaryie linkends="gcd-main">gcd</primaryie>
+</indexentry>
+
+<indexentry>
+  <primaryie>lcm</primaryie>
+  <seeie linkend="ind-gcd">gcd</seeie>
+</indexentry>
+
+</index>
+
+</book>
diff --git a/ginsh/Makefile.in b/ginsh/Makefile.in
new file mode 100644 (file)
index 0000000..88516ac
--- /dev/null
@@ -0,0 +1,82 @@
+# This is the prototype Makefile for ginsh.
+SHELL = /bin/sh
+
+# Not every make knows what CXX is, so we inherit it together with some other
+# values from configure which checks it anyways:
+CXX = @CXX@
+CXXFLAGS = @CXXFLAGS@
+CPPFLAGS = @CPPFLAGS@ -I../ -I../include
+DEFS = @DEFS@
+LIBS = @LIBS@ @LEXLIB@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+YACC = @YACC@
+
+# Here come the usual install directories in GNU-configure fashion:
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+mandir = @mandir@
+man1dir = ${mandir}/man1
+
+# This must be empty if configure couldn't find it in ${PATH}:
+MAKEDEPEND = @MAKEDEPEND@
+
+# Autoconf macro AC_PROC_INSTALL sets these:
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ -s
+
+OBJECTS=y.tab.o @LEX_OUTPUT_ROOT@.o ../src/*.o
+
+all:   depend ginsh
+
+ginsh: ${OBJECTS}
+       ${CXX} ${CXXFLAGS} ${LDFLAGS} ${OBJECTS} ${LIBS} -o ginsh
+
+# Targets for installation in install directories.
+install: ginsh installdirs
+       ${INSTALL_PROGRAM} ginsh ${bindir}/ginsh
+       -${INSTALL_DATA} ginsh.1 ${man1dir}/ginsh.1
+
+installdirs:
+       ${SHELL} mkinstalldirs ${bindir} ${man1dir}
+
+# Targets for cleaning up. (clean deletes files created by built, distclean
+# deletes files created by configuration, uninstall removes all files related
+# to ginsh from the system.)
+clean:
+       rm -f y.tab.c y.tab.h @LEX_OUTPUT_ROOT@.c
+       rm -f *.o *.lo core ginsh
+
+distclean: clean
+       rm -f config.status config.log config.cache config.h Makefile Makefile.bak
+
+uninstall:
+       rm -f ${bindir}/ginsh
+       rm -f ${man1dir}/ginsh.1
+
+# If Todd Brunhoff's makedepend is installed (it may not---it's part of X11);
+# then call it; else wait for trouble ahead; fi;    # :-)
+depend:
+       @if [ ${MAKEDEPEND} ]; then \
+               echo "calling ${MAKEDEPEND}"; \
+               ${MAKEDEPEND} -Y. -Y../include *.cpp 2> /dev/null; \
+       fi
+
+# Special dummy targets:
+.PHONY: clean distclean depend all install uninstall check doc
+.SUFFIXES: .o .c .h .y .l
+
+# Suffix rules:
+.c.o :
+       ${CXX} ${CPPFLAGS} ${CXXFLAGS} ${DEFS} -c $<
+
+# Explicit rules:
+y.tab.c y.tab.h: ginsh.y
+       $(YACC) -d ginsh.y
+
+@LEX_OUTPUT_ROOT@.c: ginsh.l
+       $(LEX) ginsh.l
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
diff --git a/ginsh/ginsh.1 b/ginsh/ginsh.1
new file mode 100644 (file)
index 0000000..69c3783
--- /dev/null
@@ -0,0 +1,408 @@
+.TH ginsh 1 "October, 1999" "GiNaC"
+.SH NAME
+ginsh \- GiNaC Interactive Shell
+.SH SYNPOSIS
+.B ginsh
+.SH DESCRIPTION
+.B ginsh
+is an interactive frontend for the GiNaC symbolic computation framework.
+It is intended as a tool for testing and experimenting with GiNaC's
+features, not as a replacement for traditional interactive computer
+algebra systems. Although it can do many things these traditional systems
+can do, ginsh provides no programming constructs like loops or conditional
+expressions. If you need this functionality you are advised to write
+your program in C++, using the "native" GiNaC class framework.
+.SH USAGE
+.SS INPUT FORMAT
+After startup, ginsh displays a prompt ("> ") signifying that it is ready
+to accept your input. Acceptable input are numeric or symbolic expressions
+consisting of numbers (e.g.
+.BR 42 ", " 2/3 " or " 0.17 ),
+symbols (e.g.
+.BR x " or " result ),
+mathematical operators like
+.BR + " and  " * ,
+and functions (e.g.
+.BR sin " or " normal ).
+ginsh will evaluate the expression and print the result to stdout. Every
+input expression must be terminated by a semicolon
+.RB ( ; ),
+and it is possible to enter multiple expressions on one line. Whitespace
+(spaces, tabs, newlines) can be applied freely between tokens. To quit ginsh,
+enter
+.BR quit " or " exit ,
+or type an EOF (Ctrl-D) at the prompt.
+.SS NUMBERS
+ginsh accepts numbers in all formats accepted by CLN (the Class Library for
+Numbers, that is the foundation of GiNaC's numerics). This includes arbitrary
+precision integers and rationals as well as floating point numbers in standard
+or scientific notation (e.g.
+.BR 1.2E6 ).
+The general rule is that if a number contains a decimal point
+.RB ( . ),
+it is an (inexact) floating point number; otherwise it is an (exact) integer or
+rational.
+.SS SYMBOLS
+Symbols are made up of a string of alphanumeric characters and the underscore
+.RB ( _ ),
+with the first character being non-numeric. E.g.
+.BR a " and " mu_1
+are acceptable symbol names, while
+.B 2pi
+is not. It is possible to use symbols with the same names as functions (e.g.
+.BR sin );
+ginsh is able to distinguish between the two.
+.PP
+Symbols can be assigned values by entering
+.RS
+.IB symbol " = " expression ;
+.RE
+.PP
+To unassign the value of an assigned symbol, type
+.RS
+.BI unassign(' symbol ');
+.RE
+.PP
+Assigned symbols are automatically evaluated (= replaced by their assigned value)
+when they are used. To refer to the unevaluated symbol, put single quotes
+.RB ( ' )
+around the name, as demonstrated for the "unassign" command above.
+.PP
+The following symbols are pre-defined constants that cannot be assigned
+a value by the user:
+.RS
+.TP 8m
+.B Pi
+Archimedes' Constant
+.TP
+.B Catalan
+Catalan's Constant
+.TP
+.B EulerGamma
+Euler-Mascheroni Constant
+.TP
+.B I
+(-1)^1/2
+.TP
+.B FAIL
+an object of the GiNaC "fail" class
+.RE
+.PP
+There is also the special
+.RS
+.B Digits
+.RE
+symbol that controls the numeric precision of calculations with inexact numbers.
+Assigning an integer value to digits will change the precision to the given
+number of decimal places.
+.SS LAST PRINTED EXPRESSIONS
+ginsh provides the three special symbols
+.RS
+", "" and """
+.RE
+that refer to the last, second last, and third last printed expression, respectively.
+These are handy if you want to use the results of previous computations in a new
+expression.
+.SS OPERATORS
+ginsh provides the following operators, listed in falling order of precedence:
+.RS
+.TP 8m
+.B !
+postfix factorial
+.TP
+.B ^
+powering
+.TP
+.B +
+unary plus
+.TP
+.B \-
+unary minus
+.TP
+.B *
+multiplication
+.TP
+.B %
+non-commutative multiplication
+.TP
+.B /
+division
+.TP
+.B +
+addition
+.TP
+.B \-
+subtraction
+.TP
+.B <
+less than
+.TP
+.B >
+greater than
+.TP
+.B <=
+less or equal
+.TP
+.B >=
+greater or equal
+.TP
+.B ==
+equal
+.TP
+.B !=
+not equal
+.TP
+.B =
+symbol assignment
+.RE
+.PP
+All binary operators are left-associative, with the exception of
+.BR ^ " and " =
+which are right-associative. The result of the assignment operator
+.RB ( = )
+is its right-hand side, so it's possible to assign multiple symbols in one
+expression (e.g.
+.BR "a = b = c = 2;" ).
+.SS LISTS
+Lists are used by the
+.B subs
+and
+.B lsolve
+functions. A list consists of an opening square bracket
+.RB ( [ ),
+a (possibly empty) comma-separated sequence of expressions, and a closing square
+bracket
+.RB ( ] ).
+.SS MATRICES
+A matrix consists of an opening double square bracket
+.RB ( [[ ),
+a non-empty comma-separated sequence of matrix rows, and a closing double square
+bracket
+.RB ( ]] ).
+Each matrix row consists of an opening double square bracket
+.RB ( [[ ),
+a non-empty comma-separated sequence of expressions, and a closing double square
+bracket
+.RB ( ]] ).
+If the rows of a matrix are not of the same length, the width of the matrix
+becomes that of the longest row and shorter rows are filled up at the end
+with elements of value zero.
+.SS FUNCTIONS
+A function call in ginsh has the form
+.RS
+.IB name ( arguments )
+.RE
+where
+.I arguments
+is a comma-separated sequence of expressions. ginsh provides a couple of built-in
+functions and also "imports" all symbolic functions defined by GiNaC and additional
+libraries. There is no way to define your own functions other than linking ginsh
+against a library that defines symbolic GiNaC functions.
+.PP
+ginsh provides Tab-completion on function names: if you type the first part of
+a function name, hitting Tab will complete the name if possible. If the part you
+typed is not unique, hitting Tab again will display a list of matching functions.
+Hitting Tab twice at the prompt will display the list of all available functions.
+.PP
+A list of the built-in functions follows. They nearly all work as the
+respective GiNaC methods of the same name, so I will not describe them in
+detail here. Please refer to the GiNaC documentation.
+.PP
+.RS
+.BI beta( expression ", " expression )
+.br
+.BI charpoly( matrix ", " symbol )
+.br
+.BI coeff( expression ", " symbol ", " number )
+.br
+.BI collect( expression ", " symbol )
+.br
+.BI content( expression ", " symbol )
+.br
+.BI degree( expression ", " symbol )
+.br
+.BI denom( expression )
+.br
+.BI determinant( matrix )
+.br
+.BI diag( expression... )
+.br
+.BI diff( expression ", " "symbol [" ", " number] )
+.br
+.BI divide( expression ", " expression )
+.br
+.BI eval( "expression [" ", " number] )
+.br
+.BI evalf( "expression [" ", " number] )
+.br
+.BI expand( expression )
+.br
+.BI gcd( expression ", " expression )
+.br
+.BI has( expression ", " expression )
+.br
+.BI inverse( matrix )
+.br
+.BI is( relation )
+\- returns "1" if the
+.I relation
+is true, "0" otherwise (false or undecided)
+.br
+.BI lcm( expression ", " expression )
+.br
+.BI lcoeff( expression ", " symbol )
+.br
+.BI ldegree( expression ", " symbol )
+.br
+.BI lsolve( list ", " list )
+.br
+.BI nops( expression )
+.br
+.BI normal( "expression [" ", " number] )
+.br
+.BI numer( expression )
+.br
+.BI op( expression ", " number )
+.br
+.BI power( expression ", " expression )
+.br
+.BI prem( expression ", " expression ", " symbol )
+.br
+.BI primpart( expression ", " symbol )
+.br
+.BI quo( expression ", " expression ", " symbol )
+.br
+.BI rem( expression ", " expression ", " symbol )
+.br
+.BI series( expression ", " "symbol [" ", " "number [" ", " number]] )
+.br
+.BI sqrfree( expression ", " symbol )
+.br
+.BI sqrt( expression )
+.br
+.BI subs( expression ", " relation-or-list )
+.br
+.BI subs( expression ", " list ", " list )
+.br
+.BI tcoeff( expression ", " symbol )
+.br
+.BI time( expression )
+\- returns the time in seconds needed to evaluate the given
+.I expression
+.br
+.BI trace( matrix )
+.br
+.BI transpose( matrix )
+.br
+.BI unassign( symbol )
+.br
+.BI unit( expression ", " symbol )
+.RE
+.SS SPECIAL COMMANDS
+To exit ginsh, enter
+.RS
+.B quit
+.RE
+or
+.RS
+.B exit
+.RE
+.PP
+The command
+.RS
+.BI print( expression );
+.RE
+will print a dump of GiNaC's internal representation for the given
+.IR expression .
+This is useful for debugging and for learning about GiNaC internals.
+.PP
+Finally, the shell escape
+.RS
+.B !
+.RI [ "command  " [ arguments ]]
+.RE
+passes the given
+.I command
+and optionally
+.I arguments
+to the shell for execution. With this method, you can execute shell commands
+from within ginsh without having to quit.
+.SH EXAMPLES
+.nf
+> a = x^2\-x\-2;
+\-x+x^2\-2
+> b = (x+1)^2;
+(x+1)^2
+> s = a/b;
+(x+1)^(\-2)*(\-x+x^2\-2)
+> diff(s, x);
+(2*x\-1)*(x+1)^(\-2)\-2*(x+1)^(\-3)*(\-x+x^2\-2)
+> normal(s);
+(x\-2)*(x+1)^(\-1)
+> x = 3^50;
+717897987691852588770249
+> s;
+717897987691852588770247/717897987691852588770250
+> Digits = 40;
+40
+> evalf(s);
+0.999999999999999999999995821133292704384960990679L0
+> unassign('x');
+x
+> s;
+(x+1)^(\-2)*(\-x+x^2\-2)
+> lsolve([3*x+5*y == 7], [x, y]);
+[x==\-5/3*y+7/3,y==y]
+> lsolve([3*x+5*y == 7, \-2*x+10*y == \-5], [x, y]);
+[x==19/8,y==\-1/40]
+> M = [[ [[a, b]], [[c, d]] ]];
+[[ [[\-x+x^2\-2,(x+1)^2]], [[c,d]] ]]
+> determinant(M);
+\-2*d\-2*x*c\-x^2*c\-x*d+x^2*d\-c
+> collect(", x);
+(\-d\-2*c)*x+(d\-c)*x^2\-2*d\-c
+> quit
+.fi
+.SH DIAGNOSTICS
+.TP
+.RI "parse error at " foo
+You entered something which ginsh was unable to parse. Please check the syntax
+of your input and try again.
+.TP
+.RI "argument " num " to " function " must be a " type
+The argument number
+.I num
+to the given
+.I function
+must be of a certain type (e.g. a symbol, or a list). The first argument has
+number 0, the second argument number 1, etc.
+.SH AUTHOR
+.TP
+The GiNaC Group:
+.br
+Christian Bauer <Christian.Bauer@uni-mainz.de>
+.br
+Alexander Frink <Alexander.Frink@uni-mainz.de>
+.br
+Richard B. Kreckel <Richard.Kreckel@uni-mainz.de>
+.SH SEE ALSO
+GiNaC Tutorial \- An open framework for symbolic computation within the
+C++ programming language
+.PP
+CLN \- A Class Library for Numbers, Bruno Haible
+.SH COPYRIGHT
+Copyright \(co 1999 Johannes Gutenberg Universit\(:at Mainz, Germany
+
+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/ginsh/ginsh.h b/ginsh/ginsh.h
new file mode 100644 (file)
index 0000000..24f37c0
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  ginsh.h - GiNaC Interactive Shell, global definitions
+ */
+
+#ifndef GINSH_H_
+#define GINSH_H_
+
+// yacc semantic type
+#define YYSTYPE ex
+
+// lex functions/variables
+extern int yyerror(char *s);
+extern int yylex(void);
+#if YYTEXT_POINTER
+extern char *yytext;
+#else
+extern char yytext[];
+#endif
+
+// Table of all used symbols
+typedef map<string, symbol> sym_tab;
+extern sym_tab syms;
+
+// Ersatz functions
+#ifndef HAVE_STRDUP
+char *strdup(const char *s)
+{
+       char *n = (char *)malloc(strlen(s) + 1);
+       strcpy(n, s);
+       return n;
+}
+#endif
+
+#endif
diff --git a/ginsh/ginsh.l b/ginsh/ginsh.l
new file mode 100644 (file)
index 0000000..f46f949
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ *  ginsh.l - GiNaC Interactive Shell, lexical analyzer definition
+ *
+ *  This file must be processed with flex
+ */
+
+
+/*
+ *  Definitions
+ */
+
+%{
+#include "config.h"
+
+#if STDC_HEADERS
+#include <stdio.h>
+#endif
+
+extern "C" {
+#include <readline/readline.h>
+#include <readline/history.h>
+}
+#include <map>
+
+#include <ginac.h>
+
+#include "ginsh.h"
+#include "y.tab.h"
+
+#define YY_INPUT(buf, result, max_size) (result = ginsh_input(buf, max_size))
+
+// Table of all used symbols
+sym_tab syms;
+
+// lex input function
+static int ginsh_input(char *buf, int max_size);
+%}
+
+       /* Abbreviations */
+D      [0-9]
+E      [elEL][-+]?{D}+
+A      [a-zA-Z_]
+AN     [0-9a-zA-Z_]
+
+
+/*
+ *  Lexical rules
+ */
+
+%%
+[ \t\n]+               /* skip whitespace */
+\\$                    /* skip line continuations */
+"#".*                  /* skip comments starting with "#" */
+^"!".*                 system(yytext + 1);     /* execute shell command */
+
+                       /* special values */
+Pi                     yylval = Pi; return T_LITERAL;
+EulerGamma             yylval = EulerGamma; return T_LITERAL;
+Catalan                        yylval = Catalan; return T_LITERAL;
+FAIL                   yylval = *new fail(); return T_LITERAL;
+I                      yylval = I; return T_NUMBER;
+Digits                 yylval = (long)Digits; return T_DIGITS;
+
+                       /* keywords */
+quit|exit              return T_QUIT;
+print                  return T_PRINT;
+time                   return T_TIME;
+xyzzy                  return T_XYZZY;
+inventory              return T_INVENTORY;
+look                   return T_LOOK;
+score                  return T_SCORE;
+
+                       /* comparison */
+"=="                   return T_EQUAL;
+"!="                   return T_NOTEQ;
+"<="                   return T_LESSEQ;
+">="                   return T_GREATEREQ;
+
+                       /* last 1..3 expressions */
+\"                     return T_QUOTE;
+\"\"                   return T_QUOTE2;
+\"\"\"                 return T_QUOTE3;
+
+                       /* matrix delimiters */
+\[\[                   return T_MATRIX_BEGIN;
+\]\]                   return T_MATRIX_END;
+
+                       /* numbers */
+{D}+                   |
+{D}+"."{D}*({E})?      |
+{D}*"."{D}+({E})?      |
+{D}+{E}                        yylval = numeric(yytext); return T_NUMBER;
+
+                       /* symbols */
+{A}{AN}*               {
+                               if (syms.find(yytext) == syms.end())
+                                       syms[yytext] = *(new symbol(yytext));
+                               yylval = syms[yytext];
+                               return T_SYMBOL;
+                       }
+
+                       /* everything else */
+.                      return *yytext;
+
+%%
+
+
+/*
+ *  Routines
+ */
+
+static int line_length = 0;
+static char *line_read = NULL;
+static char *line_ptr;
+
+// Input function that uses libreadline for interactive input
+static int ginsh_input(char *buf, int max_size)
+{
+       int result;
+       if (yy_current_buffer->yy_is_interactive) {
+               int actual;
+
+               // Do we need to read a new line?
+               if (line_length == 0) {
+
+                       // Free old line
+                       if (line_read)
+                               free(line_read);
+
+                       // Read new line, prompt "> "
+                       line_read = line_ptr = readline("> ");
+
+                       // EOF?
+                       if (!line_read) {
+                               line_length = 0;
+                               return YY_NULL;
+                       }
+
+                       // Add non-empty lines to history
+                       line_length = strlen(line_read) + 1;
+                       if (line_length > 1)
+                               add_history(line_read);
+
+                       // Reappend trailing '\n' which is stripped by readline()
+                       line_read[line_length - 1] = '\n';
+               }
+
+               // Copy data to lex buffer
+               actual = line_length > max_size ? max_size : line_length;
+               memcpy(buf, line_ptr, actual);
+               line_length -= actual;
+               line_ptr += actual;
+               result = actual;
+
+       } else if (((result = fread(buf, 1, max_size, yyin)) == 0) && ferror(yyin))
+               YY_FATAL_ERROR("input in flex scanner failed");
+
+       return result;
+}
diff --git a/ginsh/ginsh.y b/ginsh/ginsh.y
new file mode 100644 (file)
index 0000000..143eae5
--- /dev/null
@@ -0,0 +1,659 @@
+/*
+ *  ginsh.y - GiNaC Interactive Shell, input grammar definition
+ *
+ *  This file must be processed with yacc/bison
+ */
+
+
+/*
+ *  Definitions
+ */
+
+%{
+#include "config.h"
+
+#include <sys/resource.h>
+
+#if HAVE_UNISTD_H
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#if STDC_HEADERS
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+extern "C" {
+#include <readline/readline.h>
+#include <readline/history.h>
+}
+#include <map>
+#include <string>
+#include <stdexcept>
+
+#include <ginac.h>
+
+#include "ginsh.h"
+
+// Original readline settings
+static int orig_completion_append_character;
+static char *orig_basic_word_break_characters;
+
+// Expression stack for ", "" and """
+static void push(const ex &e);
+static ex exstack[3];
+
+// Start and end time for the time() function
+static struct rusage start_time, end_time;
+
+// Table of functions (a multimap, because one function may appear with different
+// numbers of parameters)
+typedef ex (*fcnp)(const exprseq &e);
+typedef ex (*fcnp2)(const exprseq &e, int serial);
+
+struct fcn_desc {
+       fcn_desc() : p(NULL), num_params(0) {}
+       fcn_desc(fcnp func, int num) : p(func), num_params(num), is_ginac(false) {}
+       fcn_desc(fcnp2 func, int num, int ser) : p((fcnp)func), num_params(num), is_ginac(true), serial(ser) {}
+
+       fcnp p;         // Pointer to function
+       int num_params; // Number of parameters (0 = arbitrary)
+       bool is_ginac;  // Flag: function is GiNaC function
+       int serial;     // GiNaC function serial number (if is_ginac == true)
+};
+
+typedef multimap<string, fcn_desc> fcn_tab;
+static fcn_tab fcns;
+
+static fcn_tab::const_iterator find_function(const ex &sym, int req_params);
+
+static ex lst2matrix(const ex &l);
+%}
+
+/* Tokens (T_LITERAL means a literal value returned by the parser, but not
+   of class numeric or symbol (e.g. a constant or the FAIL object)) */
+%token T_NUMBER T_SYMBOL T_LITERAL T_DIGITS T_QUOTE T_QUOTE2 T_QUOTE3
+%token T_EQUAL T_NOTEQ T_LESSEQ T_GREATEREQ T_MATRIX_BEGIN T_MATRIX_END
+
+%token T_QUIT T_PRINT T_TIME T_XYZZY T_INVENTORY T_LOOK T_SCORE
+
+/* Operator precedence and associativity */
+%right '='
+%left T_EQUAL T_NOTEQ
+%left '<' '>' T_LESSEQ T_GREATEREQ
+%left '+' '-'
+%left '*' '/' '%'
+%nonassoc NEG
+%right '^'
+%nonassoc '!'
+
+%start input
+
+
+/*
+ *  Grammar rules
+ */
+
+%%
+input  : /* empty */
+       | input line
+       ;
+
+line   : ';'
+       | exp ';'
+               {
+                       try {
+                               cout << $1 << endl;
+                               push($1);
+                       } catch (exception &e) {
+                               cerr << e.what() << endl;
+                               YYERROR;
+                       }
+               }
+       | T_PRINT '(' exp ')' ';'
+               {
+                       try {
+                               $3.printtree(cout);
+                       } catch (exception &e) {
+                               cerr << e.what() << endl;
+                               YYERROR;
+                       }
+               }
+       | T_QUIT                {YYACCEPT;}
+       | T_XYZZY               {cout << "Nothing happens.\n";}
+       | T_INVENTORY           {cout << "You're not carrying anything.\n";}
+       | T_LOOK                {cout << "You're in a twisty little maze of passages, all alike.\n";}
+       | T_SCORE
+               {
+                       cout << "If you were to quit now, you would score ";
+                       cout << (syms.size() > 350 ? 350 : syms.size());
+                       cout << " out of a possible 350.\n";
+               }
+       | error ';'             {yyclearin; yyerrok;}
+       ;
+
+exp    : T_NUMBER              {$$ = $1;}
+       | T_SYMBOL              {$$ = $1.eval();}
+       | '\'' T_SYMBOL '\''    {$$ = $2;}
+       | T_LITERAL             {$$ = $1;}
+       | T_DIGITS              {$$ = $1;}
+       | T_QUOTE               {$$ = exstack[0];}
+       | T_QUOTE2              {$$ = exstack[1];}
+       | T_QUOTE3              {$$ = exstack[2];}
+       | T_TIME {getrusage(RUSAGE_SELF, &start_time);} '(' exp ')'
+               {
+                       getrusage(RUSAGE_SELF, &end_time);
+                       $$ = (end_time.ru_utime.tv_sec - start_time.ru_utime.tv_sec) +
+                            (end_time.ru_stime.tv_sec - start_time.ru_stime.tv_sec) +
+                            double(end_time.ru_utime.tv_usec - start_time.ru_utime.tv_usec) / 1e6 +
+                            double(end_time.ru_stime.tv_usec - start_time.ru_stime.tv_usec) / 1e6;
+               }
+       | T_SYMBOL '(' exprseq ')'
+               {
+                       fcn_tab::const_iterator i = find_function($1, $3.nops());
+                       if (i->second.is_ginac) {
+                               $$ = ((fcnp2)(i->second.p))(static_cast<const exprseq &>(*($3.bp)), i->second.serial);
+                       } else {
+                               $$ = (i->second.p)(static_cast<const exprseq &>(*($3.bp)));
+                       }
+               }
+       | T_DIGITS '=' T_NUMBER
+               {$$ = $3; Digits = ex_to_numeric($3).to_int();}
+       | T_SYMBOL '=' exp
+               {$$ = $3; const_cast<symbol *>(&ex_to_symbol($1))->assign($3);}
+       | exp T_EQUAL exp       {$$ = $1 == $3;}
+       | exp T_NOTEQ exp       {$$ = $1 != $3;}
+       | exp '<' exp           {$$ = $1 < $3;}
+       | exp T_LESSEQ exp      {$$ = $1 <= $3;}
+       | exp '>' exp           {$$ = $1 > $3;}
+       | exp T_GREATEREQ exp   {$$ = $1 >= $3;}
+       | exp '+' exp           {$$ = $1 + $3;}
+       | exp '-' exp           {$$ = $1 - $3;}
+       | exp '*' exp           {$$ = $1 * $3;}
+       | exp '/' exp           {$$ = $1 / $3;}
+       | exp '%' exp           {$$ = $1 % $3;}
+       | '-' exp %prec NEG     {$$ = -$2;}
+       | '+' exp %prec NEG     {$$ = $2;}
+       | exp '^' exp           {$$ = power($1, $3);}
+       | exp '!'               {$$ = factorial($1);}
+       | '(' exp ')'           {$$ = $2;}
+       | '[' list_or_empty ']' {$$ = $2;}
+       | T_MATRIX_BEGIN matrix T_MATRIX_END    {$$ = lst2matrix($2);}
+       ;
+
+exprseq        : exp                   {$$ = exprseq($1);}
+       | exprseq ',' exp       {exprseq es(static_cast<exprseq &>(*($1.bp))); $$ = es.append($3);}
+       ;
+
+list_or_empty: /* empty */     {$$ = *new lst;}
+       | list                  {$$ = $1;}
+       ;
+
+list   : exp                   {$$ = lst($1);}
+       | list ',' exp          {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($3);}
+       ;
+
+matrix : T_MATRIX_BEGIN row T_MATRIX_END               {$$ = lst($2);}
+       | matrix ',' T_MATRIX_BEGIN row T_MATRIX_END    {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($4);}
+       ;
+
+row    : exp                   {$$ = lst($1);}
+       | row ',' exp           {lst l(static_cast<lst &>(*($1.bp))); $$ = l.append($3);}
+       ;
+
+
+/*
+ *  Routines
+ */
+
+%%
+const int GINSH_VERSION = 0;
+const int GINSH_REVISION = 3;
+
+// Error print routine
+int yyerror(char *s)
+{
+       cerr << s << " at " << yytext << endl;
+       return 0;
+}
+
+// Push expression "e" onto the expression stack (for ", "" and """)
+static void push(const ex &e)
+{
+       exstack[2] = exstack[1];
+       exstack[1] = exstack[0];
+       exstack[0] = 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();}
+static ex f_expand(const exprseq &e) {return e[0].expand();}
+static ex f_gcd(const exprseq &e) {return gcd(e[0], e[1]);}
+static ex f_lcm(const exprseq &e) {return lcm(e[0], e[1]);}
+static ex f_lsolve(const exprseq &e) {return lsolve(e[0], e[1]);}
+static ex f_nops(const exprseq &e) {return e[0].nops();}
+static ex f_normal1(const exprseq &e) {return e[0].normal();}
+static ex f_numer(const exprseq &e) {return e[0].numer();}
+static ex f_power(const exprseq &e) {return power(e[0], e[1]);}
+static ex f_sqrt(const exprseq &e) {return sqrt(e[0]);}
+static ex f_subs2(const exprseq &e) {return e[0].subs(e[1]);}
+
+#define CHECK_ARG(num, type, fcn) if (!is_ex_of_type(e[num], type)) throw(std::invalid_argument("argument " #num " to " #fcn " must be a " #type))
+
+static ex f_charpoly(const exprseq &e)
+{
+       CHECK_ARG(0, matrix, charpoly);
+       CHECK_ARG(1, symbol, charpoly);
+       return ex_to_matrix(e[0]).charpoly(ex_to_symbol(e[1]));
+}
+
+static ex f_coeff(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, coeff);
+       CHECK_ARG(2, numeric, coeff);
+       return e[0].coeff(ex_to_symbol(e[1]), ex_to_numeric(e[2]).to_int());
+}
+
+static ex f_collect(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, collect);
+       return e[0].collect(ex_to_symbol(e[1]));
+}
+
+static ex f_content(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, content);
+       return e[0].content(ex_to_symbol(e[1]));
+}
+
+static ex f_degree(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, degree);
+       return e[0].degree(ex_to_symbol(e[1]));
+}
+
+static ex f_determinant(const exprseq &e)
+{
+       CHECK_ARG(0, matrix, determinant);
+       return ex_to_matrix(e[0]).determinant();
+}
+
+static ex f_diag(const exprseq &e)
+{
+       int dim = e.nops();
+       matrix &m = *new matrix(dim, dim);
+       for (int i=0; i<dim; i++)
+               m.set(i, i, e.op(i));
+       return m;
+}
+
+static ex f_diff2(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, diff);
+       return e[0].diff(ex_to_symbol(e[1]));
+}
+
+static ex f_diff3(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, diff);
+       CHECK_ARG(2, numeric, diff);
+       return e[0].diff(ex_to_symbol(e[1]), ex_to_numeric(e[2]).to_int());
+}
+
+static ex f_divide(const exprseq &e)
+{
+       ex q;
+       if (divide(e[0], e[1], q))
+               return q;
+       else
+               return *new fail();
+}
+
+static ex f_eval2(const exprseq &e)
+{
+       CHECK_ARG(1, numeric, eval);
+       return e[0].eval(ex_to_numeric(e[1]).to_int());
+}
+
+static ex f_evalf2(const exprseq &e)
+{
+       CHECK_ARG(1, numeric, evalf);
+       return e[0].evalf(ex_to_numeric(e[1]).to_int());
+}
+
+static ex f_has(const exprseq &e)
+{
+       return e[0].has(e[1]) ? exONE() : exZERO();
+}
+
+static ex f_inverse(const exprseq &e)
+{
+       CHECK_ARG(0, matrix, inverse);
+       return ex_to_matrix(e[0]).inverse();
+}
+
+static ex f_is(const exprseq &e)
+{
+       CHECK_ARG(0, relational, is);
+       return (bool)ex_to_relational(e[0]) ? exONE() : exZERO();
+}
+
+static ex f_lcoeff(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, lcoeff);
+       return e[0].lcoeff(ex_to_symbol(e[1]));
+}
+
+static ex f_ldegree(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, ldegree);
+       return e[0].ldegree(ex_to_symbol(e[1]));
+}
+
+static ex f_normal2(const exprseq &e)
+{
+       CHECK_ARG(1, numeric, normal);
+       return e[0].normal(ex_to_numeric(e[1]).to_int());
+}
+
+static ex f_op(const exprseq &e)
+{
+       CHECK_ARG(1, numeric, op);
+       int n = ex_to_numeric(e[1]).to_int();
+       if (n < 0 || n >= e[0].nops())
+               throw(std::out_of_range("second argument to op() is out of range"));
+       return e[0].op(n);
+}
+
+static ex f_prem(const exprseq &e)
+{
+       CHECK_ARG(2, symbol, prem);
+       return prem(e[0], e[1], ex_to_symbol(e[2]));
+}
+
+static ex f_primpart(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, primpart);
+       return e[0].primpart(ex_to_symbol(e[1]));
+}
+
+static ex f_quo(const exprseq &e)
+{
+       CHECK_ARG(2, symbol, quo);
+       return quo(e[0], e[1], ex_to_symbol(e[2]));
+}
+
+static ex f_rem(const exprseq &e)
+{
+       CHECK_ARG(2, symbol, rem);
+       return rem(e[0], e[1], ex_to_symbol(e[2]));
+}
+
+static ex f_series2(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, series);
+       return e[0].series(ex_to_symbol(e[1]), exZERO());
+}
+
+static ex f_series3(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, series);
+       return e[0].series(ex_to_symbol(e[1]), e[2]);
+}
+
+static ex f_series4(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, series);
+       CHECK_ARG(3, numeric, series);
+       return e[0].series(ex_to_symbol(e[1]), e[2], ex_to_numeric(e[3]).to_int());
+}
+
+static ex f_sqrfree(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, sqrfree);
+       return sqrfree(e[0], ex_to_symbol(e[1]));
+}
+
+static ex f_subs3(const exprseq &e)
+{
+       CHECK_ARG(1, lst, subs);
+       CHECK_ARG(2, lst, subs);
+       return e[0].subs(ex_to_lst(e[1]), ex_to_lst(e[2]));
+}
+
+static ex f_tcoeff(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, tcoeff);
+       return e[0].tcoeff(ex_to_symbol(e[1]));
+}
+
+static ex f_trace(const exprseq &e)
+{
+       CHECK_ARG(0, matrix, trace);
+       return ex_to_matrix(e[0]).trace();
+}
+
+static ex f_transpose(const exprseq &e)
+{
+       CHECK_ARG(0, matrix, transpose);
+       return ex_to_matrix(e[0]).transpose();
+}
+
+static ex f_unassign(const exprseq &e)
+{
+       CHECK_ARG(0, symbol, unassign);
+       (const_cast<symbol *>(&ex_to_symbol(e[0])))->unassign();
+       return e[0];
+}
+
+static ex f_unit(const exprseq &e)
+{
+       CHECK_ARG(1, symbol, unit);
+       return e[0].unit(ex_to_symbol(e[1]));
+}
+
+static ex f_dummy(const exprseq &e)
+{
+       throw(std::logic_error("dummy function called (shouldn't happen)"));
+}
+
+
+/*
+ *  Add all registered GiNaC functions to ginsh
+ */
+
+static ex f_ginac_function(const exprseq &es, int serial)
+{
+       return function(serial, es).eval(1);
+}
+
+void ginsh_get_ginac_functions(void)
+{
+       vector<registered_function_info>::const_iterator i = function::registered_functions().begin(), end = function::registered_functions().end();
+       unsigned serial = 0;
+       while (i != end) {
+               fcns.insert(make_pair(i->name, fcn_desc(f_ginac_function, i->nparams, serial)));
+               i++;
+               serial++;
+       }
+}
+
+
+/*
+ *  Find a function given a name and number of parameters. Throw exceptions on error.
+ */
+
+static fcn_tab::const_iterator find_function(const ex &sym, int req_params)
+{
+       const string &name = ex_to_symbol(sym).getname();
+       typedef fcn_tab::const_iterator I;
+       pair<I, I> b = fcns.equal_range(name);
+       if (b.first == b.second)
+               throw(std::logic_error("unknown function '" + name + "'"));
+       else {
+               for (I i=b.first; i!=b.second; i++)
+                       if ((i->second.num_params == 0) || (i->second.num_params == req_params))
+                               return i;
+       }
+       throw(std::logic_error("invalid number of arguments to " + name + "()"));
+}
+
+
+/*
+ *  Convert list of lists to matrix
+ */
+
+static ex lst2matrix(const ex &l)
+{
+       if (!is_ex_of_type(l, lst))
+               throw(std::logic_error("internal error: argument to lst2matrix() is not a list"));
+
+       // Find number of rows and columns
+       int rows = l.nops(), cols = 0, i, j;
+       for (i=0; i<rows; i++)
+               if (l.op(i).nops() > cols)
+                       cols = l.op(i).nops();
+
+       // Allocate and fill matrix
+       matrix &m = *new matrix(rows, cols);
+       for (i=0; i<rows; i++)
+               for (j=0; j<cols; j++)
+                       if (l.op(i).nops() > j)
+                               m.set(i, j, l.op(i).op(j));
+                       else
+                               m.set(i, j, exZERO());
+       return m;
+}
+
+
+/*
+ *  Function name completion functions for readline
+ */
+
+static char *fcn_generator(char *text, int state)
+{
+       static int len;                         // Length of word to complete
+       static fcn_tab::const_iterator index;   // Iterator to function being currently considered
+
+       // If this is a new word to complete, initialize now
+       if (state == 0) {
+               index = fcns.begin();
+               len = strlen(text);
+       }
+
+       // Return the next function which partially matches
+       while (index != fcns.end()) {
+               const char *fcn_name = index->first.c_str();
+               index++;
+               if (strncmp(fcn_name, text, len) == 0)
+                       return strdup(fcn_name);
+       }
+       return NULL;
+}
+
+static char **fcn_completion(char *text, int start, int end)
+{
+       if (rl_line_buffer[0] == '!') {
+               // For shell commands, revert back to filename completion
+               rl_completion_append_character = orig_completion_append_character;
+               rl_basic_word_break_characters = orig_basic_word_break_characters;
+               return completion_matches(text, filename_completion_function);
+       } else {
+               // Otherwise, complete function names
+               rl_completion_append_character = '(';
+               rl_basic_word_break_characters = " \t\n\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~";
+               return completion_matches(text, fcn_generator);
+       }
+}
+
+
+/*
+ *  Main program
+ */
+
+int main(int argc, char **argv)
+{
+       // Print banner in interactive mode
+       if (isatty(0)) {
+               cout << "ginsh - GiNaC Interactive Shell V" << GINSH_VERSION << "." << GINSH_REVISION << endl;
+               cout << "Copyright (C) 1999 Johannes Gutenberg Universitaet Mainz, Germany\n";
+               cout << "This is free software, and you are welcome to redistribute it\n";
+               cout << "under certain conditions; see the file COPYING for details.\n"; 
+       }
+
+       // Init table of built-in functions
+       fcns.insert(make_pair(string("beta"), fcn_desc(f_beta, 2)));
+       fcns.insert(make_pair(string("charpoly"), fcn_desc(f_charpoly, 2)));
+       fcns.insert(make_pair(string("coeff"), fcn_desc(f_coeff, 3)));
+       fcns.insert(make_pair(string("collect"), fcn_desc(f_collect, 2)));
+       fcns.insert(make_pair(string("content"), fcn_desc(f_content, 2)));
+       fcns.insert(make_pair(string("degree"), fcn_desc(f_degree, 2)));
+       fcns.insert(make_pair(string("denom"), fcn_desc(f_denom, 1)));
+       fcns.insert(make_pair(string("determinant"), fcn_desc(f_determinant, 1)));
+       fcns.insert(make_pair(string("diag"), fcn_desc(f_diag, 0)));
+       fcns.insert(make_pair(string("diff"), fcn_desc(f_diff2, 2)));
+       fcns.insert(make_pair(string("diff"), fcn_desc(f_diff3, 3)));
+       fcns.insert(make_pair(string("divide"), fcn_desc(f_divide, 2)));
+       fcns.insert(make_pair(string("eval"), fcn_desc(f_eval1, 1)));
+       fcns.insert(make_pair(string("eval"), fcn_desc(f_eval2, 2)));
+       fcns.insert(make_pair(string("evalf"), fcn_desc(f_evalf1, 1)));
+       fcns.insert(make_pair(string("evalf"), fcn_desc(f_evalf2, 2)));
+       fcns.insert(make_pair(string("expand"), fcn_desc(f_expand, 1)));
+       fcns.insert(make_pair(string("gcd"), fcn_desc(f_gcd, 2)));
+       fcns.insert(make_pair(string("has"), fcn_desc(f_has, 2)));
+       fcns.insert(make_pair(string("inverse"), fcn_desc(f_inverse, 1)));
+       fcns.insert(make_pair(string("is"), fcn_desc(f_is, 1)));
+       fcns.insert(make_pair(string("lcm"), fcn_desc(f_lcm, 2)));
+       fcns.insert(make_pair(string("lcoeff"), fcn_desc(f_lcoeff, 2)));
+       fcns.insert(make_pair(string("ldegree"), fcn_desc(f_ldegree, 2)));
+       fcns.insert(make_pair(string("lsolve"), fcn_desc(f_lsolve, 2)));
+       fcns.insert(make_pair(string("nops"), fcn_desc(f_nops, 1)));
+       fcns.insert(make_pair(string("normal"), fcn_desc(f_normal1, 1)));
+       fcns.insert(make_pair(string("normal"), fcn_desc(f_normal2, 2)));
+       fcns.insert(make_pair(string("numer"), fcn_desc(f_numer, 1)));
+       fcns.insert(make_pair(string("op"), fcn_desc(f_op, 2)));
+       fcns.insert(make_pair(string("power"), fcn_desc(f_power, 2)));
+       fcns.insert(make_pair(string("prem"), fcn_desc(f_prem, 3)));
+       fcns.insert(make_pair(string("primpart"), fcn_desc(f_primpart, 2)));
+       fcns.insert(make_pair(string("quo"), fcn_desc(f_quo, 3)));
+       fcns.insert(make_pair(string("rem"), fcn_desc(f_rem, 3)));
+       fcns.insert(make_pair(string("series"), fcn_desc(f_series2, 2)));
+       fcns.insert(make_pair(string("series"), fcn_desc(f_series3, 3)));
+       fcns.insert(make_pair(string("series"), fcn_desc(f_series4, 4)));
+       fcns.insert(make_pair(string("sqrfree"), fcn_desc(f_sqrfree, 2)));
+       fcns.insert(make_pair(string("sqrt"), fcn_desc(f_sqrt, 1)));
+       fcns.insert(make_pair(string("subs"), fcn_desc(f_subs2, 2)));
+       fcns.insert(make_pair(string("subs"), fcn_desc(f_subs3, 3)));
+       fcns.insert(make_pair(string("tcoeff"), fcn_desc(f_tcoeff, 2)));
+       fcns.insert(make_pair(string("time"), fcn_desc(f_dummy, 0)));
+       fcns.insert(make_pair(string("trace"), fcn_desc(f_trace, 1)));
+       fcns.insert(make_pair(string("transpose"), fcn_desc(f_transpose, 1)));
+       fcns.insert(make_pair(string("unassign"), fcn_desc(f_unassign, 1)));
+       fcns.insert(make_pair(string("unit"), fcn_desc(f_unit, 2)));
+       ginsh_get_ginac_functions();
+
+       // Init readline completer
+       rl_readline_name = argv[0];
+       rl_attempted_completion_function = (CPPFunction *)fcn_completion;
+       orig_completion_append_character = rl_completion_append_character;
+       orig_basic_word_break_characters = rl_basic_word_break_characters;
+
+       // Parse input, catch all remaining exceptions
+       int result;
+again: try {
+               result = yyparse();
+       } catch (exception &e) {
+               cerr << e.what() << endl;
+               goto again;
+       }
+       return result;
+}