--- /dev/null
+ 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.
--- /dev/null
+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.
--- /dev/null
+# 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
+
--- /dev/null
+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
+])
--- /dev/null
+# 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 $<
--- /dev/null
+// 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_
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
--- /dev/null
+---------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)
--- /dev/null
+// 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;
+}
--- /dev/null
+/* 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__
--- /dev/null
+#! /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"
--- /dev/null
+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"
--- /dev/null
+# 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 =
--- /dev/null
+# 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 =
--- /dev/null
+<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>
+
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+#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
--- /dev/null
+\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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+<!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ä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 <GiNaC/ginac.h>
+
+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 << poly << 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 <GiNaC/ginac.h>
+
+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 << "H_" << i << "(z) == " << HermitePoly(z,i) << 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 <GiNaC/ginac.h>
+
+int main()
+{
+ symbol x("x"), y("y"), z("z");
+ ex e1, e2;
+
+ e1 = sin(x + 2*y) + 3*z + 41;
+ e2 = e1; // e2 points to same object as e1
+ cout << e2 << endl; // prints sin(x+2*y)+3*z+41
+ e2 += 1; // e2 is copied into a new object
+ cout << e2 << endl; // prints sin(x+2*y)+3*z+42
+ // ...
+}
+</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 <GiNaC/ginac.h>
+
+int main()
+{
+ symbol x("x"), y("y");
+
+ ex e1 = x + 3*y;
+ ex e2 = pow(e1, 3);
+ ex e3 = diff(sin(e2), x); // first derivative of sin(e2) by x
+ cout << e1 << endl // prints x+3*y
+ << e2 << endl // prints (x+3*y)^3
+ << e3 << endl; // prints 3*(x+3*y)^2*cos((x+3*y)^3)
+ // ...
+}
+</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 <GiNaC/ginac.h>
+
+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 << two*p << 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
+<GiNaC/ginac.h>
+
+void foo()
+{
+ numeric three(3.0), one(1.0);
+ numeric x = one/three;
+
+ cout << "in " << Digits << " digits:" << endl;
+ cout << x << endl;
+ cout << Pi.evalf() << 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 <GiNaC/ginac.h>
+
+int main()
+{
+ numeric twentyone(21);
+ numeric ten(10);
+ numeric answer(21,5);
+
+ cout << answer.is_integer() << endl; // false, it's 21/5
+ answer *= ten;
+ cout << answer.is_integer() << 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 <GiNaC/ginac.h>
+
+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 <GiNaC/ginac.h>
+
+int main()
+{
+ ex x = numeric(1.0);
+
+ cout << "As method: " << sin(x).evalf() << endl;
+ cout << "As function: " << evalf(sin(x)) << 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 <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 <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 <GiNaC/ginac.h>
+
+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 << "The x^" << i << "-coefficient is "
+ << Poly.coeff(x,i) << endl;
+ }
+ cout << "As polynomial in y: "
+ << Poly.collect(y) << 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 <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 <GiNaC/ginac.h>
+
+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 <GiNaC/ginac.h>
+
+int main()
+{
+ symbol x("x"), y("y"), z("z");
+ ex P = pow(x, 5) + pow(x, 2) + y;
+
+ cout << P.diff(x,2) << endl; // 20*x^3 + 2
+ cout << P.diff(y) << endl; // 1
+ cout << P.diff(z) << endl; // 0
+ // ...
+}
+</programlisting>
+</example>
+</para>
+
+<para>
+<example><title>Differentiation with nontrivial functions</title>
+<programlisting>
+#include <GiNaC/ginac.h>
+
+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 <GiNaC/ginac.h>
+
+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 << MyExpr1 << " == " << MyTailor
+ << " for small " << x << endl;
+ MySeries = MyExpr2.series(x, numZERO(), 7);
+ cout << MyExpr2 << " == " << MySeries
+ << " for small " << x << 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>
--- /dev/null
+# 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.
--- /dev/null
+.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.
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}