From: Richard Kreckel Date: Mon, 8 Nov 1999 21:43:49 +0000 (+0000) Subject: Initial revision X-Git-Tag: rising-foo~1 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=commitdiff_plain;h=5c0989497994b35faa9c17b18f936c21dbb22d78 Initial revision --- diff --git a/COPYING b/COPYING new file mode 100644 index 00000000..12065f35 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + 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.) + +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. + + 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. + + 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 + + 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. + + + Copyright (C) 19yy + + 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. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..750d5164 --- /dev/null +++ b/INSTALL @@ -0,0 +1,27 @@ +Installation: +============= + +As with any autoconfiguring GNU software, installation is as easy as this: + +sysprompt> ./configure +sysprompt> make +sysprompt> make check +sysprompt> make install + +Known to work with: + - Linux/x86, EGCS-1.1.2 or GCC 2-95. + +The "make" step takes about 10 minutes, on a 586 DX / 133 MHz / 64 MB or +about 2 minutes on a P-III /550 MHz / 512 MB. + +More detailed installation instructions can be found in the documentation, +in the doc/ directory. + + +Problems with CLN: +================== + +You should use at least CLN V1.0.2, since all earlier ones are +somewhat buggy. Even V1.0.1 has a few problems and GiNaC will not +support older versions. Please install it properly on your system +before continuing with GiNaC. diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000..8eae8513 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,115 @@ +# This is the prototype Makefile for the GiNaC package. + +# Not every make knows what CXX is, so we inherit it together with some other +# values from configure which checks it anyways: +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CPPFLAGS = @CPPFLAGS@ +DEFS = @DEFS@ +LIBS = @LIBS@ +LDFLAGS = @LDFLAGS@ + +# Here come the usual install directories in GNU-configure fashion: +srcdir = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +includedir = @includedir@/GiNaC + +# This must be empty unless the user has called configure with --enable-shared: +shared = @shared@ + +# The version-number is tracked in configure.in only: +LIBGINACVER = @LibGiNaC_Ver@ + +# Autoconf macro AC_PROC_INSTALL sets these: +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +all: lib ginsh + echo "now type make install" + +src/libginac.la: + cd src; ${MAKE} libginac.la + +src/.libs/libginac.a: + cd src; ${MAKE} .libs/libginac.a + +lib: + cd src; ${MAKE} all + +# Target for running a test-suite across the library: +check: + if [ "${shared}" ]; then \ + ${MAKE} sharedcheck; \ + else \ + ${MAKE} staticcheck; \ + fi + +sharedcheck: src/libginac.la + cd check; ${MAKE} sharedcheck + +staticcheck: src/.libs/libginac.a + cd check; ${MAKE} staticcheck + +# Target for making the Ginac INteractive SHell ginsh: +ginsh: + cd ginsh; ${MAKE} all + +# Targets for installation in install directories. The user-visible target +# `install' determines which one to call (static lib only or both shared and +# static lib). +install: + @ if [ "${shared}" ]; then \ + ${MAKE} shlibinst; \ + else \ + ${MAKE} libinst; \ + fi + ${INSTALL} -d ${includedir} + ${INSTALL_DATA} include/* ${includedir}/ + cd ginsh; ${MAKE} install + cd doc; ${MAKE} install + +shlibinst: libginac.la + ${INSTALL} -d ${libdir} + ${LIBTOOL} install libginac.la ${libdir}/libginac.la + ${LIBTOOL} -n --finish ${libdir} + +libinst: .libs/libginac.a + ${INSTALL} -d ${libdir} + ${INSTALL_DATA} .libs/libginac.a ${libdir}/libginac.a + +# Targets for cleaning up. (clean deletes files created by built, distclean +# deletes files created by configuration, uninstall removes all files related +# to GiNaC from the system.) +clean: + cd src; ${MAKE} clean + cd check; ${MAKE} clean + cd ginsh; ${MAKE} clean + +distclean: clean + cd src; ${MAKE} distclean + cd check; ${MAKE} distclean + cd ginsh; ${MAKE} distclean + rm -f config.status config.log config.cache config.h Makefile + +uninstall: + rm -f ${libdir}/libginac.* + rm -rf ${includedir} + cd ginsh; ${MAKE} uninstall + cd doc; ${MAKE} uninstall + +# Convenient targets for those who wish to extend on the documentation: +doc: + cd doc; ${MAKE} all +reference: + cd doc; ${MAKE} reference +tutorial: + cd doc; ${MAKE} tutorial + +# Special dummy targets: +.PHONY: clean distclean all install uninstall check ginsh doc +.SUFFIXES: .o .lo .cpp +.SILENT: all check sharedcheck staticcheck doc reference tutorial + diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 00000000..fff18399 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,116 @@ +dnl =========================================================================== +dnl Additional macros used to configure GiNaC. We don't start additions' names +dnl with AC_ but with GINAC_ in order to avoid future trouble. +dnl =========================================================================== + +dnl Generally, it is a bad idea to put specialized header files for a library +dnl into a generic directory like /usr/local/include/. Instead, one should put +dnl them into a subdirectory. GiNaC does it, NTL does it. Unfortunately, CLN +dnl doesn't do so but some people choose to do it by hand. In these cases we +dnl need to #include , otherwise #include . 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 ], + [factorial(1);], + ginac_cv_lib_cln_link="-lcln", + ginac_cv_lib_cln_link="fail") + ;; + *) + AC_TRY_LINK([#include ], + [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 +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 +int main() { +cl_RA q(3); q = q/2; cl_RA p(3); p = p/2; +if (q+p != 3) return 1; else return 0; +}], + ginac_cv_lib_cln_integrity="sane", + ginac_cv_lib_cln_integrity="insane", + ginac_cv_lib_cln_integrity="guessing sane") + ;; + esac + ]) + case "${ginac_cv_lib_cln_integrity}" in +dnl exit status was 0: + "sane") + AC_MSG_RESULT([yes]) + ;; +dnl exit status was not 0: + "insane") + AC_MSG_RESULT([no]) + AC_MSG_WARN([maybe version of libcln is older than 1.0.2?]) + ;; +dnl test-program was not run because we are cross-compiling: + "guessing sane") + AC_MSG_RESULT([hopefully]) + ;; +dnl should never ever get here: + *) + AC_MSG_WARN([you found a bug in the configure script!]) + ;; + esac +]) diff --git a/check/Makefile.in b/check/Makefile.in new file mode 100644 index 00000000..6572b14b --- /dev/null +++ b/check/Makefile.in @@ -0,0 +1,58 @@ +# This is the Makefile for GiNaC's consistency checks. + +# Not every make knows what CXX is, so we inherit it together with some other +# values from configure which checks it anyways: +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CPPFLAGS = @CPPFLAGS@ -I../include +DEFS = @DEFS@ +LIBS = @LIBS@ +LDFLAGS = @LDFLAGS@ + +# Here come the usual install directories in GNU-configure fashion: +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +includedir = @includedir@ + +# This must be empty unless the user has called configure with --enable-shared: +shared = @shared@ + +OBJECTS = paranoia_check.o numeric_output.o numeric_consist.o powerlaws.o \ + expand_subs.o inifcns_consist.o differentiation.o poly_gcd.o \ + normalization.o lsolve_onedim.o matrix_checks.o series_expansion.o \ + fcntimer.o main.o + +all: + echo "Please call it with 'make check' from top-level Makefile." + echo "Alternatively, you can use this Makefile's targets {shared|static}check" + echo "depending on your personal preferences and which lib you built." + +sharedcheck: ${OBJECTS} ../src/.libs/libginac.so + ${CXX} ${LDFLAGS} ${OBJECTS} -Wl,--rpath -Wl,../src/.libs -L../src/.libs -lginac ${LIBS} -o main + @echo -n "Running " + ./main 2> result.out + @echo -n "comparing output: " + cmp result.ref result.out + +staticcheck: ${OBJECTS} ../src/.libs/libginac.a + ${CXX} ${LDFLAGS} ${OBJECTS} ../src/.libs/libginac.a ${LIBS} -o main + @echo -n "Running " + ./main 2> result.out + @echo -n "comparing output: " + cmp result.ref result.out + +# Special dummy targets: +.PHONY: clean distclean all sharedcheck staticcheck +.SUFFIXES: .o .cpp +.SILENT: all + +clean: + rm -f *.o main core result.out + +distclean: clean + rm -f Makefile + +# Suffix rules: +.cpp.o : + ${CXX} ${CPPFLAGS} ${CXXFLAGS} ${DEFS} -c $< diff --git a/check/check.h b/check/check.h new file mode 100644 index 00000000..68622d96 --- /dev/null +++ b/check/check.h @@ -0,0 +1,24 @@ +// check/check.h + +#ifndef _CHECK_H_ +#define _CHECK_H_ + +// fcntimer is defined in timer.cpp and used for timing check functions only: +unsigned fcntimer(unsigned fcn()); + +// prototypes for all individual checks must be unsigned fcn() in order to be +// able to use fcntimer() as a wrapper: +unsigned paranoia_check(); +unsigned numeric_output(); +unsigned numeric_consist(); +unsigned powerlaws(); +unsigned expand_subs(); +unsigned inifcns_consist(); +unsigned differentiation(); +unsigned poly_gcd(); +unsigned normalization(); +unsigned matrix_checks(); +unsigned lsolve_onedim(); +unsigned series_expansion(); + +#endif // ndef _CHECK_H_ diff --git a/check/differentiation.cpp b/check/differentiation.cpp new file mode 100644 index 00000000..e917bd79 --- /dev/null +++ b/check/differentiation.cpp @@ -0,0 +1,233 @@ +// check/differentiation.cpp + +/* Tests for symbolic differentiation, including various functions. */ + +#include "ginac.h" + +static unsigned check_diff(const ex &e, const symbol &x, + const ex &d, unsigned nth=1) +{ + ex ed = e.diff(x, nth); + if ((ed - d).compare(exZERO()) != 0) { + switch (nth) { + case 0: + clog << "zeroth "; + break; + case 1: + break; + case 2: + clog << "second "; + break; + case 3: + clog << "third "; + break; + default: + clog << nth << "th "; + } + clog << "derivative of " << e << " by " << x << " returned " + << ed << " instead of " << d << endl; + clog << "returned:" << endl; + ed.printtree(clog); + clog << endl << "instead of" << endl; + d.printtree(clog); + + return 1; + } + return 0; +} + +// Simple (expanded) polynomials +static unsigned differentiation1(void) +{ + unsigned result = 0; + symbol x("x"), y("y"); + ex e1, e2, e, d; + + // construct bivariate polynomial e to be diff'ed: + e1 = pow(x, -2) * 3 + pow(x, -1) * 5 + 7 + x * 11 + pow(x, 2) * 13; + e2 = pow(y, -2) * 5 + pow(y, -1) * 7 + 11 + y * 13 + pow(y, 2) * 17; + e = (e1 * e2).expand(); + + // d e / dx: + d = 121 - 55*pow(x,-2) - 66*pow(x,-3) - 30*pow(x,-3)*pow(y,-2) + - 42*pow(x,-3)*pow(y,-1) - 78*pow(x,-3)*y + - 102*pow(x,-3)*pow(y,2) - 25*pow(x,-2) * pow(y,-2) + - 35*pow(x,-2)*pow(y,-1) - 65*pow(x,-2)*y + - 85*pow(x,-2)*pow(y,2) + 77*pow(y,-1) + 143*y + 187*pow(y,2) + + 130*x*pow(y,-2) + 182*pow(y,-1)*x + 338*x*y + 442*x*pow(y,2) + + 55*pow(y,-2) + 286*x; + result += check_diff(e, x, d); + + // d e / dy: + d = 91 - 30*pow(x,-2)*pow(y,-3) - 21*pow(x,-2)*pow(y,-2) + + 39*pow(x,-2) + 102*pow(x,-2)*y - 50*pow(x,-1)*pow(y,-3) + - 35*pow(x,-1)*pow(y,-2) + 65*pow(x,-1) + 170*pow(x,-1)*y + - 77*pow(y,-2)*x + 143*x + 374*x*y - 130*pow(y,-3)*pow(x,2) + - 91*pow(y,-2)*pow(x,2) + 169*pow(x,2) + 442*pow(x,2)*y + - 110*pow(y,-3)*x - 70*pow(y,-3) + 238*y - 49*pow(y,-2); + result += check_diff(e, y, d); + + // d^2 e / dx^2: + d = 286 + 90*pow(x,-4)*pow(y,-2) + 126*pow(x,-4)*pow(y,-1) + + 234*pow(x,-4)*y + 306*pow(x,-4)*pow(y,2) + + 50*pow(x,-3)*pow(y,-2) + 70*pow(x,-3)*pow(y,-1) + + 130*pow(x,-3)*y + 170*pow(x,-3)*pow(y,2) + + 130*pow(y,-2) + 182*pow(y,-1) + 338*y + 442*pow(y,2) + + 198*pow(x,-4) + 110*pow(x,-3); + result += check_diff(e, x, d, 2); + + // d^2 e / dy^2: + d = 238 + 90*pow(x,-2)*pow(y,-4) + 42*pow(x,-2)*pow(y,-3) + + 102*pow(x,-2) + 150*pow(x,-1)*pow(y,-4) + + 70*pow(x,-1)*pow(y,-3) + 170*pow(x,-1) + 330*x*pow(y,-4) + + 154*x*pow(y,-3) + 374*x + 390*pow(x,2)*pow(y,-4) + + 182*pow(x,2)*pow(y,-3) + 442*pow(x,2) + 210*pow(y,-4) + + 98*pow(y,-3); + result += check_diff(e, y, d, 2); + + return result; +} + +// Trigonometric and transcendental functions +static unsigned differentiation2(void) +{ + unsigned result = 0; + symbol x("x"), y("y"), a("a"), b("b"); + ex e1, e2, e, d; + + // construct expression e to be diff'ed: + e1 = y*pow(x, 2) + a*x + b; + e2 = sin(e1); + e = b*pow(e2, 2) + y*e2 + a; + + d = 2*b*e2*cos(e1)*(2*x*y + a) + y*cos(e1)*(2*x*y + a); + result += check_diff(e, x, d); + + d = 2*b*pow(cos(e1),2)*pow(2*x*y + a, 2) + 4*b*y*e2*cos(e1) + - 2*b*pow(e2,2)*pow(2*x*y + a, 2) - y*e2*pow(2*x*y + a, 2) + + 2*pow(y,2)*cos(e1); + result += check_diff(e, x, d, 2); + + d = 2*b*e2*cos(e1)*pow(x, 2) + e2 + y*cos(e1)*pow(x, 2); + result += check_diff(e, y, d); + + d = 2*b*pow(cos(e1),2)*pow(x,4) - 2*b*pow(e2,2)*pow(x,4) + + 2*cos(e1)*pow(x,2) - y*e2*pow(x,4); + result += check_diff(e, y, d, 2); + + // construct expression e to be diff'ed: + e2 = cos(e1); + e = b*pow(e2, 2) + y*e2 + a; + + d = -2*b*e2*sin(e1)*(2*x*y + a) - y*sin(e1)*(2*x*y + a); + result += check_diff(e, x, d); + + d = 2*b*pow(sin(e1),2)*pow(2*y*x + a,2) - 4*b*e2*sin(e1)*y + - 2*b*pow(e2,2)*pow(2*y*x + a,2) - y*e2*pow(2*y*x + a,2) + - 2*pow(y,2)*sin(e1); + result += check_diff(e, x, d, 2); + + d = -2*b*e2*sin(e1)*pow(x,2) + e2 - y*sin(e1)*pow(x, 2); + result += check_diff(e, y, d); + + d = -2*b*pow(e2,2)*pow(x,4) + 2*b*pow(sin(e1),2)*pow(x,4) + - 2*sin(e1)*pow(x,2) - y*e2*pow(x,4); + result += check_diff(e, y, d, 2); + + // construct expression e to be diff'ed: + e2 = exp(e1); + e = b*pow(e2, 2) + y*e2 + a; + + d = 2*b*pow(e2, 2)*(2*x*y + a) + y*e2*(2*x*y + a); + result += check_diff(e, x, d); + + d = 4*b*pow(e2,2)*pow(2*y*x + a,2) + 4*b*pow(e2,2)*y + + 2*pow(y,2)*e2 + y*e2*pow(2*y*x + a,2); + result += check_diff(e, x, d, 2); + + d = 2*b*pow(e2,2)*pow(x,2) + e2 + y*e2*pow(x,2); + result += check_diff(e, y, d); + + d = 4*b*pow(e2,2)*pow(x,4) + 2*e2*pow(x,2) + y*e2*pow(x,4); + result += check_diff(e, y, d, 2); + + // construct expression e to be diff'ed: + e2 = log(e1); + e = b*pow(e2, 2) + y*e2 + a; + + d = 2*b*e2*(2*x*y + a)/e1 + y*(2*x*y + a)/e1; + result += check_diff(e, x, d); + + d = 2*b*pow((2*x*y + a),2)*pow(e1,-2) + 4*b*y*e2/e1 + - 2*b*e2*pow(2*x*y + a,2)*pow(e1,-2) + 2*pow(y,2)/e1 + - y*pow(2*x*y + a,2)*pow(e1,-2); + result += check_diff(e, x, d, 2); + + d = 2*b*e2*pow(x,2)/e1 + e2 + y*pow(x,2)/e1; + result += check_diff(e, y, d); + + d = 2*b*pow(x,4)*pow(e1,-2) - 2*b*e2*pow(e1,-2)*pow(x,4) + + 2*pow(x,2)/e1 - y*pow(x,4)*pow(e1,-2); + result += check_diff(e, y, d, 2); + + // test for functions with two variables: atan2 + e1 = y*pow(x, 2) + a*x + b; + e2 = x*pow(y, 2) + b*y + a; + e = atan2(e1,e2); + /* + d = pow(y,2)*(-b-y*pow(x,2)-a*x)/(pow(b+y*pow(x,2)+a*x,2)+pow(x*pow(y,2)+b*y+a,2)) + +(2*y*x+a)/((x*pow(y,2)+b*y+a)*(1+pow(b*y*pow(x,2)+a*x,2)/pow(x*pow(y,2)+b*y+a,2))); + */ + /* + d = ((a+2*y*x)*pow(y*b+pow(y,2)*x+a,-1)-(a*x+b+y*pow(x,2))* + pow(y*b+pow(y,2)*x+a,-2)*pow(y,2))* + pow(1+pow(a*x+b+y*pow(x,2),2)*pow(y*b+pow(y,2)*x+a,-2),-1); + */ + d = pow(1+pow(a*x+b+y*pow(x,2),2)*pow(y*b+pow(y,2)*x+a,-2),-1) + *pow(y*b+pow(y,2)*x+a,-1)*(a+2*y*x) + +pow(y,2)*(-a*x-b-y*pow(x,2))* + pow(pow(y*b+pow(y,2)*x+a,2)+pow(a*x+b+y*pow(x,2),2),-1); + result += check_diff(e, x, d); + + return result; +} + +// Series +static unsigned differentiation3(void) +{ + symbol x("x"); + ex e, d, ed; + + e = sin(x).series(x, exZERO(), 8); + d = cos(x).series(x, exZERO(), 7); + ed = e.diff(x); + ed = static_cast(ed.bp)->convert_to_poly(); + d = static_cast(d.bp)->convert_to_poly(); + + if ((ed - d).compare(exZERO()) != 0) { + clog << "derivative of " << e << " by " << x << " returned " + << ed << " instead of " << d << ")" << endl; + return 1; + } + return 0; +} + +unsigned differentiation(void) +{ + unsigned result = 0; + + cout << "checking symbolic differentiation..." << flush; + clog << "---------symbolic differentiation:" << endl; + + result += differentiation1(); + result += differentiation2(); + result += differentiation3(); + + if (!result) { + cout << " passed "; + clog << "(no output)" << endl; + } else { + cout << " failed "; + } + return result; +} diff --git a/check/expand_subs.cpp b/check/expand_subs.cpp new file mode 100644 index 00000000..083eae54 --- /dev/null +++ b/check/expand_subs.cpp @@ -0,0 +1,78 @@ +// check/expand_subs.cpp + +/* The first test routine implements Denny Fliegner's quick consistency check: + * e = (a0 + a1 + a2 + a3 + ...)^2 + * expand e + * substitute a0 by (-a2 - a3 - ...) in e + * expand e + * after which e should be just a1^2. + * In addition, a simpler modification is tested in the second test: + * e = (a0 + a1)^200 + * expand e + * substitute a0 by -a1 in e + * after which e should return 0 (without expanding). */ + +#include "ginac.h" + +#define VECSIZE 100 + +static unsigned expand_subs1(void) +{ + symbol a1("a1"); + symbol a[VECSIZE]; + ex e, aux; + + a[1] = a1; + for (unsigned i=0; i +#include + + +// fcntimer() is a little wrapper around GiNaC's automated checks. All those +// functions are passed void and return unsigned. fcntimer() accepts one such +// function fcn(), returns its result and as a side-effect prints to stdout how +// much CPU time was consumed by fcn's execution in the fashion "(0.07s)\n". +unsigned fcntimer(unsigned fcn()) +{ + unsigned fcnresult; + struct rusage used1, used2; + double elapsed; + + // time the execution of the function: + getrusage(RUSAGE_SELF, &used1); + fcnresult = fcn(); + getrusage(RUSAGE_SELF, &used2); + + // add elapsed user and system time in microseconds: + elapsed = ((used2.ru_utime.tv_sec - used1.ru_utime.tv_sec) + + (used2.ru_stime.tv_sec - used1.ru_stime.tv_sec) + + (used2.ru_utime.tv_usec - used1.ru_utime.tv_usec) / 1e6 + + (used2.ru_stime.tv_usec - used1.ru_stime.tv_usec) / 1e6); + + printf("(%.2fs)\n", elapsed); + + return fcnresult; +} diff --git a/check/inifcns_consist.cpp b/check/inifcns_consist.cpp new file mode 100644 index 00000000..35baf29c --- /dev/null +++ b/check/inifcns_consist.cpp @@ -0,0 +1,218 @@ +// check/inifcns_consist.cpp + +/* This test routine applies assorted tests on initially known higher level + * functions. */ + +#include "ginac.h" + +/* Simple tests on the sine trigonometric function. */ +static unsigned inifcns_consist_sin(void) +{ + unsigned result = 0; + bool errorflag; + + // sin(n*Pi) == 0? + errorflag = false; + for (int n=-10; n<=10; ++n) { + if ( sin(n*Pi).eval() != numeric(0) || + !sin(n*Pi).eval().info(info_flags::integer) ) + errorflag = true; + } + if ( errorflag ) { + clog << "sin(n*Pi) with integer n does not always return exact 0" + << endl; + ++result; + } + + // sin((n+1/2)*Pi) == {+|-}1? + errorflag = false; + for (int n=-10; n<=10; ++n) { + if ( ! sin((n+numeric(1,2))*Pi).eval().info(info_flags::integer) || + !(sin((n+numeric(1,2))*Pi).eval() == numeric(1) || + sin((n+numeric(1,2))*Pi).eval() == numeric(-1)) ) + errorflag = true; + } + if ( errorflag ) { + clog << "sin((n+1/2)*Pi) with integer n does not always return exact {+|-}1" + << endl; + ++result; + } + + return result; +} + +/* Simple tests on the cosine trigonometric function. */ +static unsigned inifcns_consist_cos(void) +{ + unsigned result = 0; + bool errorflag; + + // cos((n+1/2)*Pi) == 0? + errorflag = false; + for (int n=-10; n<=10; ++n) { + if ( cos((n+numeric(1,2))*Pi).eval() != numeric(0) || + !cos((n+numeric(1,2))*Pi).eval().info(info_flags::integer) ) + errorflag = true; + } + if ( errorflag ) { + clog << "cos((n+1/2)*Pi) with integer n does not always return exact 0" + << endl; + ++result; + } + + // cos(n*Pi) == 0? + errorflag = false; + for (int n=-10; n<=10; ++n) { + if ( ! cos(n*Pi).eval().info(info_flags::integer) || + !(cos(n*Pi).eval() == numeric(1) || + cos(n*Pi).eval() == numeric(-1)) ) + errorflag = true; + } + if ( errorflag ) { + clog << "cos(n*Pi) with integer n does not always return exact {+|-}1" + << endl; + ++result; + } + + return result; +} + +/* Assorted tests on other transcendental functions. */ +static unsigned inifcns_consist_trans(void) +{ + unsigned result = 0; + symbol x("x"); + ex chk; + + chk = asin(1)-acos(0); + if (!chk.is_zero()) { + clog << "asin(1)-acos(0) erroneously returned " << chk + << " instead of 0" << endl; + ++result; + } + + // arbitrary check of type sin(f(x)): + chk = pow(sin(acos(x)),2) + pow(sin(asin(x)),2) + - (1+pow(x,2))*pow(sin(atan(x)),2); + if (chk != 1-pow(x,2)) { + clog << "sin(acos(x))^2 + sin(asin(x))^2 - (1+x^2)*sin(atan(x))^2 " + << "erroneously returned " << chk << " instead of 1-x^2" << endl; + ++result; + } + + // arbitrary check of type cos(f(x)): + chk = pow(cos(acos(x)),2) + pow(cos(asin(x)),2) + - (1+pow(x,2))*pow(cos(atan(x)),2); + if (!chk.is_zero()) { + clog << "cos(acos(x))^2 + cos(asin(x))^2 - (1+x^2)*cos(atan(x))^2 " + << "erroneously returned " << chk << " instead of 0" << endl; + ++result; + } + + // arbitrary check of type tan(f(x)): + chk = tan(acos(x))*tan(asin(x)) - tan(atan(x)); + if (chk != 1-x) { + clog << "tan(acos(x))*tan(asin(x)) - tan(atan(x)) " + << "erroneously returned " << chk << " instead of -x+1" << endl; + ++result; + } + + // arbitrary check of type sinh(f(x)): + chk = -pow(sinh(acosh(x)),2).expand()*pow(sinh(atanh(x)),2) + - pow(sinh(asinh(x)),2); + if (!chk.is_zero()) { + clog << "expand(-(sinh(acosh(x)))^2)*(sinh(atanh(x))^2) - sinh(asinh(x))^2 " + << "erroneously returned " << chk << " instead of 0" << endl; + ++result; + } + + // arbitrary check of type cosh(f(x)): + chk = (pow(cosh(asinh(x)),2) - 2*pow(cosh(acosh(x)),2)) + * pow(cosh(atanh(x)),2); + if (chk != 1) { + clog << "(cosh(asinh(x))^2 - 2*cosh(acosh(x))^2) * cosh(atanh(x))^2 " + << "erroneously returned " << chk << " instead of 1" << endl; + ++result; + } + + // arbitrary check of type tanh(f(x)): + chk = (pow(tanh(asinh(x)),-2) - pow(tanh(acosh(x)),2)).expand() + * pow(tanh(atanh(x)),2); + if (chk != 2) { + clog << "expand(tanh(acosh(x))^2 - tanh(asinh(x))^(-2)) * tanh(atanh(x))^2 " + << "erroneously returned " << chk << " instead of 2" << endl; + ++result; + } + + return result; +} + +/* Simple tests on the Gamma combinatorial function. We stuff in arguments + * where the result exists in closed form and check if it's ok. */ +static unsigned inifcns_consist_gamma(void) +{ + unsigned result = 0; + ex e; + + e = gamma(ex(1)); + for (int i=2; i<8; ++i) { + e += gamma(ex(i)); + } + if ( e != numeric(874) ) { + clog << "gamma(1)+...+gamma(7) erroneously returned " + << e << " instead of 874" << endl; + ++result; + } + + e = gamma(ex(1)); + for (int i=2; i<8; ++i) { + e *= gamma(ex(i)); + } + if ( e != numeric(24883200) ) { + clog << "gamma(1)*...*gamma(7) erroneously returned " + << e << " instead of 24883200" << endl; + ++result; + } + + e = gamma(ex(numeric(5, 2)))*gamma(ex(numeric(9, 2)))*64; + if ( e != 315*Pi ) { + clog << "64*gamma(5/2)*gamma(9/2) erroneously returned " + << e << " instead of 315*Pi" << endl; + ++result; + } + + e = gamma(ex(numeric(-13, 2))); + for (int i=-13; i<7; i=i+2) { + e += gamma(ex(numeric(i, 2))); + } + e = (e*gamma(ex(numeric(15, 2)))*numeric(512)); + if ( e != numeric(633935)*Pi ) { + clog << "512*(gamma(-13/2)+...+gamma(5/2))*gamma(15/2) erroneously returned " + << e << " instead of 633935*Pi" << endl; + ++result; + } + + return result; +} + +unsigned inifcns_consist(void) +{ + unsigned result = 0; + + cout << "checking consistency of symbolic functions..." << flush; + clog << "---------consistency of symbolic functions:" << endl; + + result += inifcns_consist_sin(); + result += inifcns_consist_cos(); + result += inifcns_consist_trans(); + result += inifcns_consist_gamma(); + + if ( !result ) { + cout << " passed "; + clog << "(no output)" << endl; + } else { + cout << " failed "; + } + + return result; +} diff --git a/check/lsolve_onedim.cpp b/check/lsolve_onedim.cpp new file mode 100644 index 00000000..d89722f2 --- /dev/null +++ b/check/lsolve_onedim.cpp @@ -0,0 +1,33 @@ +// check/lsolve_onedim.cpp + +/* This test routine does some simple checks on solving a polynomial for a + * variable. */ + +#include "ginac.h" + +unsigned lsolve_onedim(void) +{ + unsigned result = 0; + symbol x("x"); + ex eq, aux; + + cout << "checking linear solve..." << flush; + clog << "---------linear solve:" << endl; + + eq = (3*x+5 == numeric(8)); + aux = lsolve(eq,x); + if (aux != 1) { + result++; + clog << "solution of 3*x+5==8 erroneously returned " + << aux << endl; + } + + if (! result) { + cout << " passed "; + clog << "(no output)" << endl; + } else { + cout << " failed "; + } + + return result; +} diff --git a/check/main.cpp b/check/main.cpp new file mode 100644 index 00000000..1440777a --- /dev/null +++ b/check/main.cpp @@ -0,0 +1,41 @@ +// check/main.cpp + +#include "ginac.h" +#include "check.h" + +int main() +{ + unsigned result = 0; + + try { + for (int i=0; i<1; ++i) { + result += fcntimer(paranoia_check); + result += fcntimer(numeric_output); + result += fcntimer(numeric_consist); + result += fcntimer(powerlaws); + result += fcntimer(expand_subs); + result += fcntimer(inifcns_consist); + result += fcntimer(differentiation); + result += fcntimer(poly_gcd); + result += fcntimer(normalization); + result += fcntimer(matrix_checks); + result += fcntimer(lsolve_onedim); + result += fcntimer(series_expansion); + } + } catch (exception const & e) { + cout << "error: caught an exception: " << e.what() << endl; + } + + if (result) { + cout << "error: something went wrong. "; + if (result == 1) { + cout << "(one failure)" << endl; + } else { + cout << "(" << result << " individual failures)" << endl; + } + cout << "please check result.out against result.ref for more details." + << endl << "happy debugging!" << endl; + } + + return result; +} diff --git a/check/matrix_checks.cpp b/check/matrix_checks.cpp new file mode 100644 index 00000000..1bf8e0c8 --- /dev/null +++ b/check/matrix_checks.cpp @@ -0,0 +1,219 @@ +// check/matrix_checks.cpp + +/* Here we test manipulations on GiNaC's symbolic matrices. */ + +#include "ginac.h" +#include + +static unsigned matrix_determinants(void) +{ + unsigned result = 0; + ex det; + matrix m1(1,1), m2(2,2), m3(3,3); + symbol a("a"), b("b"), c("c"); + symbol d("d"), e("e"), f("f"); + symbol g("g"), h("h"), i("i"); + + // check symbolic trivial matrix determinant + m1.set(0,0,a); + det = m1.determinant(); + if (det != a) { + clog << "determinant of 1x1 matrix " << m1 + << " erroneously returned " << det << endl; + ++result; + } + + // check generic dense symbolic 2x2 matrix determinant + m2.set(0,0,a).set(0,1,b); + m2.set(1,0,c).set(1,1,d); + det = m2.determinant(); + if (det != (a*d-b*c)) { + clog << "determinant of 2x2 matrix " << m2 + << " erroneously returned " << det << endl; + ++result; + } + + // check generic dense symbolic 3x3 matrix determinant + m3.set(0,0,a).set(0,1,b).set(0,2,c); + m3.set(1,0,d).set(1,1,e).set(1,2,f); + m3.set(2,0,g).set(2,1,h).set(2,2,i); + det = m3.determinant().expand(); + if (det != (a*e*i - a*f*h - d*b*i + d*c*h + g*b*f - g*c*e)) { + clog << "determinant of 3x3 matrix " << m3 + << " erroneously returned " << det << endl; + ++result; + } + + // check dense numeric 3x3 matrix determinant + m3.set(0,0,numeric(0)).set(0,1,numeric(-1)).set(0,2,numeric(3)); + m3.set(1,0,numeric(3)).set(1,1,numeric(-2)).set(1,2,numeric(2)); + m3.set(2,0,numeric(3)).set(2,1,numeric(4)).set(2,2,numeric(-2)); + det = m3.determinant(); + if (det != 42) { + clog << "determinant of 3x3 matrix " << m3 + << " erroneously returned " << det << endl; + ++result; + } + + // check dense symbolic 2x2 matrix determinant + m2.set(0,0,a/(a-b)).set(0,1,numeric(1)); + m2.set(1,0,b/(a-b)).set(1,1,numeric(1)); + det = m2.determinant(true); + if (det != 1) { + clog << "determinant of 2x2 matrix " << m2 + << " erroneously returned " << det << endl; + ++result; + } + + // check characteristic polynomial + m3.set(0,0,a).set(0,1,-2).set(0,2,2); + m3.set(1,0,3).set(1,1,a-1).set(1,2,2); + m3.set(2,0,3).set(2,1,4).set(2,2,a-3); + ex p = m3.charpoly(a); + if (p != 0) { + clog << "charpoly of 3x3 matrix " << m3 + << " erroneously returned " << p << endl; + ++result; + } + + return result; +} + +static unsigned matrix_invert1(void) +{ + matrix m(1,1); + symbol a("a"); + + m.set(0,0,a); + matrix m_i = m.inverse(); + + if (m_i(0,0) != pow(a,-1)) { + clog << "inversion of 1x1 matrix " << m + << " erroneously returned " << m_i << endl; + return 1; + } + return 0; +} + +static unsigned matrix_invert2(void) +{ + matrix m(2,2); + symbol a("a"), b("b"), c("c"), d("d"); + m.set(0,0,a).set(0,1,b); + m.set(1,0,c).set(1,1,d); + matrix m_i = m.inverse(); + ex det = m.determinant().expand(); + + if ( (normal(m_i(0,0)*det) != d) || + (normal(m_i(0,1)*det) != -b) || + (normal(m_i(1,0)*det) != -c) || + (normal(m_i(1,1)*det) != a) ) { + clog << "inversion of 2x2 matrix " << m + << " erroneously returned " << m_i << endl; + return 1; + } + return 0; +} + +static unsigned matrix_invert3(void) +{ + matrix m(3,3); + symbol a("a"), b("b"), c("c"); + symbol d("d"), e("e"), f("f"); + symbol g("g"), h("h"), i("i"); + m.set(0,0,a).set(0,1,b).set(0,2,c); + m.set(1,0,d).set(1,1,e).set(1,2,f); + m.set(2,0,g).set(2,1,h).set(2,2,i); + matrix m_i = m.inverse(); + ex det = m.determinant().normal().expand(); + + if ( (normal(m_i(0,0)*det) != (e*i-f*h)) || + (normal(m_i(0,1)*det) != (c*h-b*i)) || + (normal(m_i(0,2)*det) != (b*f-c*e)) || + (normal(m_i(1,0)*det) != (f*g-d*i)) || + (normal(m_i(1,1)*det) != (a*i-c*g)) || + (normal(m_i(1,2)*det) != (c*d-a*f)) || + (normal(m_i(2,0)*det) != (d*h-e*g)) || + (normal(m_i(2,1)*det) != (b*g-a*h)) || + (normal(m_i(2,2)*det) != (a*e-b*d)) ) { + clog << "inversion of 3x3 matrix " << m + << " erroneously returned " << m_i << endl; + return 1; + } + return 0; +} + +static unsigned matrix_misc(void) +{ + unsigned result = 0; + matrix m1(2,2); + symbol a("a"), b("b"), c("c"), d("d"), e("e"), f("f"); + m1.set(0,0,a).set(0,1,b); + m1.set(1,0,c).set(1,1,d); + ex tr = trace(m1); + + // check a simple trace + if (tr.compare(a+d)) { + clog << "trace of 2x2 matrix " << m1 + << " erroneously returned " << tr << endl; + ++result; + } + + // and two simple transpositions + matrix m2 = transpose(m1); + if (m2(0,0) != a || m2(0,1) != c || m2(1,0) != b || m2(1,1) != d) { + clog << "transpose of 2x2 matrix " << m1 + << " erroneously returned " << m2 << endl; + ++result; + } + matrix m3(3,2); + m3.set(0,0,a).set(0,1,b); + m3.set(1,0,c).set(1,1,d); + m3.set(2,0,e).set(2,1,f); + if (transpose(transpose(m3)) != m3) { + clog << "transposing 3x2 matrix " << m3 << " twice" + << " erroneously returned " << transpose(transpose(m3)) << endl; + ++result; + } + + // produce a runtime-error by inverting a singular matrix and catch it + matrix m4(2,2); + matrix m5; + bool caught=false; + try { + m5 = inverse(m4); + } + catch (std::runtime_error err) { + caught=true; + } + if (!caught) { + cerr << "singular 2x2 matrix " << m4 + << " erroneously inverted to " << m5 << endl; + ++result; + } + + return result; +} + +unsigned matrix_checks(void) +{ + unsigned result = 0; + + cout << "checking symbolic matrix manipulations..." << flush; + clog << "---------symbolic matrix manipulations:" << endl; + + result += matrix_determinants(); + result += matrix_invert1(); + result += matrix_invert2(); + result += matrix_invert3(); + result += matrix_misc(); + + if (! result) { + cout << " passed "; + clog << "(no output)" << endl; + } else { + cout << " failed "; + } + + return result; +} diff --git a/check/normalization.cpp b/check/normalization.cpp new file mode 100644 index 00000000..83befd85 --- /dev/null +++ b/check/normalization.cpp @@ -0,0 +1,113 @@ +// check/normalization.cpp + +/* Rational function normalization test-suite. */ + +#include "ginac.h" + +static symbol x("x"), y("y"), z("z"); + +static unsigned check_normal(const ex &e, const ex &d) +{ + ex en = e.normal(); + if (en.compare(d) != 0) { + clog << "normal form of " << e << " is " << en << " (should be " << d << ")" << endl; + return 1; + } + return 0; +} + +static unsigned normal1(void) +{ + unsigned result = 0; + ex e, d; + + // Expansion + e = pow(x, 2) - (x+1)*(x-1) - 1; + d = exZERO(); + result += check_normal(e, d); + + // Expansion inside functions + e = sin(x*(x+1)-x) + 1; + d = sin(pow(x, 2)) + 1; + result += check_normal(e, d); + + // Fraction addition + e = numeric(2)/x + y/3; + d = (x*y/3 + 2) / x; + result += check_normal(e, d); + + // Fraction addition + e = pow(x, -1) + x/(x+1); + d = (pow(x, 2)+x+1)/(x*(x+1)); + result += check_normal(e, d); + + // Fraction cancellation + e = (pow(x, 2) - pow(y, 2)) / pow(x-y, 3); + d = (x + y) / (pow(x, 2) + pow(y, 2) - x * y * 2); + result += check_normal(e, d); + + // Fraction cancellation + e = (pow(x, -1) + x) / (pow(x , 2) * 2 + 2); + d = pow(x * 2, -1); + result += check_normal(e, d); + + // Distribution of powers + e = pow(x/y, 2); + d = pow(x, 2) / pow(y, 2); + result += check_normal(e, d); + + // Distribution of powers (integer, distribute) and fraction addition + e = pow(pow(x, -1) + x, 2); + d = pow(pow(x, 2) + 1, 2) / pow(x, 2); + result += check_normal(e, d); + + // Distribution of powers (non-integer, don't distribute) and fraction addition + e = pow(pow(x, -1) + x, numeric(1)/2); + d = pow((pow(x, 2) + 1) / x, numeric(1)/2); + result += check_normal(e, d); + + // Replacement of functions with temporary symbols and fraction cancellation + e = pow(sin(x), 2) - pow(cos(x), 2); + e /= sin(x) + cos(x); + d = sin(x) - cos(x); + result += check_normal(e, d); + + // Replacement of non-integer powers with temporary symbols + e = (pow(numeric(2), numeric(1)/2) * x + x) / x; + d = pow(numeric(2), numeric(1)/2) + 1; + result += check_normal(e, d); + + // Replacement of complex numbers with temporary symbols + e = (x + y + x*I + y*I) / (x + y); + d = 1 + I; + result += check_normal(e, d); + + e = (pow(x, 2) + pow(y, 2)) / (x + y*I); + d = e; + result += check_normal(e, d); + + // More complex rational function + e = (pow(x-y*2,4)/pow(pow(x,2)-pow(y,2)*4,2)+1)*(x+y*2)*(y+z)/(pow(x,2)+pow(y,2)*4); + d = (y*2 + z*2) / (x + y*2); + result += check_normal(e, d); + + return result; +} + +unsigned normalization(void) +{ + unsigned result = 0; + + cout << "checking rational function normalization..." << flush; + clog << "---------rational function normalization:" << endl; + + result += normal1(); + + if (!result) { + cout << " passed "; + clog << "(no output)" << endl; + } else { + cout << " failed "; + } + return result; +} diff --git a/check/numeric_consist.cpp b/check/numeric_consist.cpp new file mode 100644 index 00000000..d7a5b6b8 --- /dev/null +++ b/check/numeric_consist.cpp @@ -0,0 +1,316 @@ +// check/numeric_consist.cpp + +/* This test routine creates some numbers and check the result of several + * boolean tests on these numbers like is_integer() etc... */ + +#include "ginac.h" +#include + +/* Simple and maybe somewhat pointless consistency tests of assorted tests and + * conversions. */ +static unsigned numeric_consist1(void) +{ + unsigned result = 0; + numeric test_int1(42); + numeric test_int2(5); + numeric test_rat1 = test_int1; test_rat1 /= test_int2; + test_rat1 = -test_rat1; // -42/5 + symbol a("a"); + ex e1, e2; + + if ( !test_int1.is_integer() ) { + clog << test_int1 + << " erroneously not recognized as integer" << endl; + ++result; + } + if ( !test_int1.is_rational() ) { + clog << test_int1 + << " erroneously not recognized as rational" << endl; + ++result; + } + + if ( !test_rat1.is_rational() ) { + clog << test_rat1 + << " erroneously not recognized as rational" << endl; + ++result; + } + if ( test_rat1.is_integer() ) { + clog << test_rat1 + << " erroneously recognized as integer" << endl; + ++result; + } + + int i = numeric(1984).to_int(); + if ( i-1984 ) { + clog << "conversion of " << i + << " from numeric to int failed" << endl; + ++result; + } + + e1 = test_int1; + if ( !e1.info(info_flags::posint) ) { + clog << "expression " << e1 + << " erroneously not recognized as positive integer" << endl; + ++result; + } + + e2 = test_int1 + a; + if ( ex_to_numeric(e2).is_integer() ) { + clog << "expression " << e2 + << " erroneously recognized as integer" << endl; + ++result; + } + + // The next two were two actual bugs in CLN till June, 12, 1999: + test_rat1 = numeric(3)/numeric(2); + test_rat1 += test_rat1; + if ( !test_rat1.is_integer() ) { + clog << "3/2 + 3/2 erroneously not integer 3 but instead " + << test_rat1 << endl; + ++result; + } + test_rat1 = numeric(3)/numeric(2); + numeric test_rat2 = test_rat1 + numeric(1); // 5/2 + test_rat2 -= test_rat1; // 1 + if ( !test_rat2.is_integer() ) { + clog << "5/2 - 3/2 erroneously not integer 1 but instead " + << test_rat2 << endl; + ++result; + } + + // Check some numerator and denominator calculations: + for (int i=0; i<10; ++i) { + int re_q, im_q; + do { re_q = rand(); } while (re_q == 0); + do { im_q = rand(); } while (im_q == 0); + numeric r(rand()-RAND_MAX/2, re_q); + numeric i(rand()-RAND_MAX/2, im_q); + numeric z = r + I*i; + numeric p = numer(z); + numeric q = denom(z); + numeric res = p/q; + if (res != z) { + clog << z << " erroneously transformed into " + << p << "/" << q << " by numer() and denom()" << endl; + ++result; + } + } + return result; +} + +/* We had some fun with a bug in CLN that caused it to loop forever when + * calculating expt(a,b) if b is a rational and a a nonnegative integer. + * Implementing a workaround sadly introduced another bug on May 28th 1999 + * that was fixed on May 31st. The workaround turned out to be stupid and + * the bug was finally killed in CLN on September 2nd. */ +static unsigned numeric_consist2(void) +{ + unsigned result = 0; + + ex zero = numeric(0); + ex two = numeric(2); + ex three = numeric(3); + + // The hang in this code was the reason for the original workaround + if ( pow(two,two/three) == 42 ) { + clog << "pow(2,2/3) erroneously returned 42" << endl; + ++result; // cannot happen + } + + // Actually, this used to raise a FPE after introducing the workaround + if ( two*zero != zero ) { + clog << "2*0 erroneously returned " << two*zero << endl; + ++result; + } + + // And this returned a cl_F due to the implicit call of numeric::power() + ex six = two*three; + if ( !six.info(info_flags::integer) ) { + clog << "2*3 erroneously returned the non-integer " << six << endl; + ++result; + } + + // The fix in the workaround left a whole which was fixed hours later... + ex another_zero = pow(zero,numeric(1)/numeric(2)); + if ( another_zero.compare(exZERO()) ) { + clog << "pow(0,1/2) erroneously returned" << another_zero << endl; + ++result; + } + + return result; +} + +/* Assorted tests to ensure some crucial functions behave exactly as specified + * in the documentation. */ +static unsigned numeric_consist3(void) +{ + unsigned result = 0; + numeric calc_rem, calc_quo; + numeric a, b; + + // check if irem(a, b) and irem(a, b, q) really behave like Maple's + // irem(a, b) and irem(a, b, 'q') as advertised in our documentation. + // These overloaded routines indeed need to be checked separately since + // internally they might be doing something completely different: + a = 23; b = 4; calc_rem = irem(a, b); + if ( calc_rem != 3 ) { + clog << "irem(" << a << "," << b << ") erroneously returned " + << calc_rem << endl; + ++result; + } + a = 23; b = -4; calc_rem = irem(a, b); + if ( calc_rem != 3 ) { + clog << "irem(" << a << "," << b << ") erroneously returned " + << calc_rem << endl; + ++result; + } + a = -23; b = 4; calc_rem = irem(a, b); + if ( calc_rem != -3 ) { + clog << "irem(" << a << "," << b << ") erroneously returned " + << calc_rem << endl; + ++result; + } + a = -23; b = -4; calc_rem = irem(a, b); + if ( calc_rem != -3 ) { + clog << "irem(" << a << "," << b << ") erroneously returned " + << calc_rem << endl; + ++result; + } + // and now the overloaded irem(a,b,q): + a = 23; b = 4; calc_rem = irem(a, b, calc_quo); + if ( calc_rem != 3 || calc_quo != 5 ) { + clog << "irem(" << a << "," << b << ",q) erroneously returned " + << calc_rem << " with q=" << calc_quo << endl; + ++result; + } + a = 23; b = -4; calc_rem = irem(a, b, calc_quo); + if ( calc_rem != 3 || calc_quo != -5 ) { + clog << "irem(" << a << "," << b << ",q) erroneously returned " + << calc_rem << " with q=" << calc_quo << endl; + ++result; + } + a = -23; b = 4; calc_rem = irem(a, b, calc_quo); + if ( calc_rem != -3 || calc_quo != -5 ) { + clog << "irem(" << a << "," << b << ",q) erroneously returned " + << calc_rem << " with q=" << calc_quo << endl; + ++result; + } + a = -23; b = -4; calc_rem = irem(a, b, calc_quo); + if ( calc_rem != -3 || calc_quo != 5 ) { + clog << "irem(" << a << "," << b << ",q) erroneously returned " + << calc_rem << " with q=" << calc_quo << endl; + ++result; + } + // check if iquo(a, b) and iquo(a, b, r) really behave like Maple's + // iquo(a, b) and iquo(a, b, 'r') as advertised in our documentation. + // These overloaded routines indeed need to be checked separately since + // internally they might be doing something completely different: + a = 23; b = 4; calc_quo = iquo(a, b); + if ( calc_quo != 5 ) { + clog << "iquo(" << a << "," << b << ") erroneously returned " + << calc_quo << endl; + ++result; + } + a = 23; b = -4; calc_quo = iquo(a, b); + if ( calc_quo != -5 ) { + clog << "iquo(" << a << "," << b << ") erroneously returned " + << calc_quo << endl; + ++result; + } + a = -23; b = 4; calc_quo = iquo(a, b); + if ( calc_quo != -5 ) { + clog << "iquo(" << a << "," << b << ") erroneously returned " + << calc_quo << endl; + ++result; + } + a = -23; b = -4; calc_quo = iquo(a, b); + if ( calc_quo != 5 ) { + clog << "iquo(" << a << "," << b << ") erroneously returned " + << calc_quo << endl; + ++result; + } + // and now the overloaded iquo(a,b,r): + a = 23; b = 4; calc_quo = iquo(a, b, calc_rem); + if ( calc_quo != 5 || calc_rem != 3 ) { + clog << "iquo(" << a << "," << b << ",r) erroneously returned " + << calc_quo << " with r=" << calc_rem << endl; + ++result; + } + a = 23; b = -4; calc_quo = iquo(a, b, calc_rem); + if ( calc_quo != -5 || calc_rem != 3 ) { + clog << "iquo(" << a << "," << b << ",r) erroneously returned " + << calc_quo << " with r=" << calc_rem << endl; + ++result; + } + a = -23; b = 4; calc_quo = iquo(a, b, calc_rem); + if ( calc_quo != -5 || calc_rem != -3 ) { + clog << "iquo(" << a << "," << b << ",r) erroneously returned " + << calc_quo << " with r=" << calc_rem << endl; + ++result; + } + a = -23; b = -4; calc_quo = iquo(a, b, calc_rem); + if ( calc_quo != 5 || calc_rem != -3 ) { + clog << "iquo(" << a << "," << b << ",r) erroneously returned " + << calc_quo << " with r=" << calc_rem << endl; + ++result; + } + + return result; +} + +/* Now we perform some less trivial checks about several functions which should + * return exact numbers if possible. */ +static unsigned numeric_consist4(void) +{ + unsigned result = 0; + bool passed; + + // square roots of squares of integers: + passed = true; + for (int i=0; i<42; ++i) { + if ( !sqrt(numeric(i*i)).is_integer() ) { + passed = false; + } + } + if ( !passed ) { + clog << "One or more square roots of squares of integers did not return exact integers" << endl; + ++result; + } + // square roots of squares of rationals: + passed = true; + for (int num=0; num<41; ++num) { + for (int den=1; den<42; ++den) { + if ( !sqrt(numeric(num*num)/numeric(den*den)).is_rational() ) { + passed = false; + } + } + } + if ( !passed ) { + clog << "One or more square roots of squares of rationals did not return exact integers" << endl; + ++result; + } + + return result; +} + +unsigned numeric_consist(void) +{ + unsigned result = 0; + + cout << "checking consistency of numeric types..." << flush; + clog << "---------consistency of numeric types:" << endl; + + result += numeric_consist1(); + result += numeric_consist2(); + result += numeric_consist3(); + result += numeric_consist4(); + + if ( !result ) { + cout << " passed "; + clog << "(no output)" << endl; + } else { + cout << " failed "; + } + + return result; +} diff --git a/check/numeric_output.cpp b/check/numeric_output.cpp new file mode 100644 index 00000000..f010ab79 --- /dev/null +++ b/check/numeric_output.cpp @@ -0,0 +1,37 @@ +// check/numeric_output.cpp + +#include "ginac.h" + +unsigned numeric_output(void) +{ + unsigned result = 0; + + cout << "checking output of numeric types..." << flush; + clog << "---------output of numeric types:" << endl; + + unsigned long Digits_before = Digits; + Digits = 200; + clog << "Using " << Digits << " digits" << endl; + clog << Pi << " evalfs to: " << Pi.evalf() << endl; + clog << Catalan << " evalfs to: " << Catalan.evalf() << endl; + clog << EulerGamma << " evalfs to: " << EulerGamma.evalf() << endl; + clog << "Complex integers: "; + clog << "{(0,0)=" << ex(0 + 0*I) << "} "; + clog << "{(1,0)=" << ex(1 + 0*I) << "} "; + clog << "{(1,1)=" << ex(1 + 1*I) << "} "; + clog << "{(0,1)=" << ex(0 + 1*I) << "} "; + clog << "{(-1,1)=" << ex(-1 + 1*I) << "} "; + clog << "{(-1,0)=" << ex(-1 + 0*I) << "} "; + clog << "{(-1,-1)=" << ex(-1 - 1*I) << "} "; + clog << "{(0,-1)=" << ex(0 - 1*I) << "} "; + clog << "{(1,-1)=" << ex(1 - 1*I) << "} " << endl; + Digits = Digits_before; + + if (! result) { + cout << " passed "; + } else { + cout << " failed "; + } + + return result; +} diff --git a/check/paranoia_check.cpp b/check/paranoia_check.cpp new file mode 100644 index 00000000..bc66deaf --- /dev/null +++ b/check/paranoia_check.cpp @@ -0,0 +1,230 @@ +// check/paranoia_check.cpp + +/* This set of tests checks for some of GiNaC's oopses which showed up during + * development. Things were evaluated wrongly and so. It should not find such + * a sick behaviour again. But since we are paranoic and we want to exclude + * that behaviour for good... */ + +#include "ginac.h" + +// The very first pair of historic problems had its roots in power.cpp and was +// finally resolved on April 27th. (Fixing the first on April 23rd actually +// introduced the second.) +static unsigned paranoia_check1(void) +{ + unsigned result = 0; + symbol x("x"), y("y"), z("z"); + ex e, f, g; + + e = x * y * z; + f = y * z; + g = e / f; + + // In the first one expand did not do any job at all: + if ( !g.expand().is_equal(x) ) { + clog << "e = x*y*z; f = y*z; expand(e/f) erroneously returned " + << g.expand() << endl; + ++result; + } + + // This one somehow used to return 0: + e = pow(x + 1, -1); + if (!e.expand().is_equal(e)) { + clog << "expand(pow(x + 1, -1)) erroneously returned " + << e.expand() << endl; + ++result; + } + + return result; +} + +// And here the second oops which showed up until May 17th 1999. It had to do +// with lexicographic canonicalization and thus showed up only if the variables +// had the names as given here: +static unsigned paranoia_check2(void) +{ + unsigned result = 0; + symbol x("x"), y("y"), z("z"); + ex e, f, g; + + e = x + z*x; + f = e*y; + g = f - e*y; + + // After .expand(), g should be zero: + if (!g.expand().is_equal(exZERO())) { + clog << "e = (x + z*x); f = e*y; expand(f - e*y) erroneously returned " + << g.expand() << endl; + ++result; + } + // After .eval(), g should be zero: + if (!g.eval().is_equal(exZERO())) { + clog << "e = (x + z*x); f = e*y; eval(f - e*y) erroneously returned " + << g.eval() << endl; + ++result; + } + // This actually worked already back in April. But we are very paranoic! + if (!g.expand().eval().is_equal(exZERO())) { + clog << "e = (x + z*x); f = e*y; eval(expand(f - e*y)) erroneously returned " + << g.expand().eval() << endl; + ++result; + } + + return result; +} + +// The third bug was introduced on May 18, discovered on May 19 and fixed that +// same day. It worked when x was substituted by 1 but not with other numbers: +static unsigned paranoia_check3(void) +{ + unsigned result = 0; + symbol x("x"), y("y"); + ex e, f; + + e = x*y - y; + f = e.subs(x == 2); + + if (!f.is_equal(y)) { + clog << "e = x*y - y; f = e.subs(x == 2) erroneously returned " + << f << endl; + ++result; + } + if (!f.eval().is_equal(y)) { + clog << "e = x*y - y; eval(e.subs(x == 2)) erroneously returned " + << f.eval() << endl; + ++result; + } + if (!f.expand().is_equal(y)) { + clog << "e = x*y - y; expand(e.subs(x == 2)) erroneously returned " + << f.expand() << endl; + ++result; + } + + return result; +} + +// The fourth bug was also discovered on May 19 and fixed immediately: +static unsigned paranoia_check4(void) +{ + unsigned result = 0; + symbol x("x"); + ex e, f, g; + + e = pow(x, 2) + x + 1; + f = pow(x, 2) + x + 1; + g = e - f; + + if (!g.is_equal(exZERO())) { + clog << "e = pow(x,2) + x + 1; f = pow(x,2) + x + 1; g = e-f; g erroneously returned " + << g << endl; + ++result; + } + if (!g.is_equal(exZERO())) { + clog << "e = pow(x,2) + x + 1; f = pow(x,2) + x + 1; g = e-f; g.eval() erroneously returned " + << g.eval() << endl; + ++result; + } + + return result; +} + +// The fifth oops was discovered on May 20 and fixed a day later: +static unsigned paranoia_check5(void) +{ + unsigned result = 0; + symbol x("x"), y("y"); + + ex e, f; + e = pow(x*y + 1, 2); + f = pow(x, 2) * pow(y, 2) + 2*x*y + 1; + + if (!(e-f).expand().is_equal(exZERO())) { + clog << "e = pow(x*y+1,2); f = pow(x,2)*pow(y,2) + 2*x*y + 1; (e-f).expand() erroneously returned " + << (e-f).expand() << endl; + ++result; + } + + return result; +} + +// This one was discovered on Jun 1 and fixed the same day: +static unsigned paranoia_check6(void) +{ + unsigned result = 0; + symbol x("x"); + + ex e, f; + e = pow(x, -5); + f = e.denom(); + + if (!f.is_equal(pow(x, 5))) { + clog << "e = pow(x, -5); f = e.denom(); f was " << f << " (should be x^5)" << endl; + ++result; + } + return result; +} + +// This one was introduced on June 1 by some aggressive manual optimization. +// Discovered and fixed on June 2. +static unsigned paranoia_check7(void) +{ + unsigned result = 0; + symbol x("x"), y("y"); + + ex e = y + y*x + 2; + ex f = expand(pow(e, 2) - (e*y*(x + 1))); + + if (f.nops() > 3) { + clog << "e=y+y*x+2; f=expand(pow(e,2)-(e*y*(x+1))) has " + << f.nops() << " arguments instead of 3 ( f==" + << f << " )" << endl; + ++result; + } + return result; +} + +// This one was a result of the rewrite of mul::max_coefficient when we +// introduced the overall_coefficient field in expairseq objects on Oct 1. +// Fixed on Oct 4. +static unsigned paranoia_check8(void) +{ + unsigned result = 0; + symbol x("x"); + + ex e = -x / (x+1); + ex f = e.normal(); + + // The bug caused a division by zero in normal(), so the following + // check is actually bogus... + if (!f.is_equal(e)) { + clog << "normal(-x/(x+1)) returns " << f << " instead of -x/(x+1)\n"; + ++result; + } + return result; +} + +unsigned paranoia_check(void) +{ + unsigned result = 0; + + cout << "checking several ex-bugs just out of pure paranoia..." << flush; + clog << "---------several ex-bugs just out of pure paranoia:" << endl; + + result += paranoia_check1(); + result += paranoia_check2(); + result += paranoia_check3(); + result += paranoia_check4(); + result += paranoia_check5(); + result += paranoia_check6(); + result += paranoia_check7(); + result += paranoia_check8(); + + if (! result) { + cout << " passed "; + clog << "(no output)" << endl; + } else { + cout << " failed "; + } + + return result; +} diff --git a/check/poly_gcd.cpp b/check/poly_gcd.cpp new file mode 100644 index 00000000..6f81f6aa --- /dev/null +++ b/check/poly_gcd.cpp @@ -0,0 +1,238 @@ +// check/poly_gcd.cpp + +/* Some test with polynomial GCD calculations. See also the checks for + * rational function normalization in normalization.cpp. */ + +#include "ginac.h" + +const int MAX_VARIABLES = 5; + +static symbol x("x"), z("z"); +static symbol y[MAX_VARIABLES]; + +// GCD = 1 +static unsigned poly_gcd1(void) +{ + for (int v=1; v<=MAX_VARIABLES; v++) { + ex e1 = x; + ex e2 = pow(x, 2); + for (int i=0; i(es.bp)->convert_to_poly(); + if ((ep - d).compare(exZERO()) != 0) { + clog << "series expansion of " << e << " at " << point + << " erroneously returned " << ep << " (instead of " << d + << ")" << endl; + (ep-d).printtree(clog); + return 1; + } + return 0; +} + +// Series expansion +static unsigned series1(void) +{ + unsigned result = 0; + ex e, d; + + e = sin(x); + d = x - pow(x, 3) / 6 + pow(x, 5) / 120 - pow(x, 7) / 5040 + Order(pow(x, 8)); + result += check_series(e, exZERO(), d); + + e = cos(x); + d = 1 - pow(x, 2) / 2 + pow(x, 4) / 24 - pow(x, 6) / 720 + Order(pow(x, 8)); + result += check_series(e, exZERO(), d); + + e = exp(x); + d = 1 + x + pow(x, 2) / 2 + pow(x, 3) / 6 + pow(x, 4) / 24 + pow(x, 5) / 120 + pow(x, 6) / 720 + pow(x, 7) / 5040 + Order(pow(x, 8)); + result += check_series(e, exZERO(), d); + + e = pow(1 - x, -1); + d = 1 + x + pow(x, 2) + pow(x, 3) + pow(x, 4) + pow(x, 5) + pow(x, 6) + pow(x, 7) + Order(pow(x, 8)); + result += check_series(e, exZERO(), d); + + e = x + pow(x, -1); + d = x + pow(x, -1); + result += check_series(e, exZERO(), d); + + e = x + pow(x, -1); + d = 2 + pow(x-1, 2) - pow(x-1, 3) + pow(x-1, 4) - pow(x-1, 5) + pow(x-1, 6) - pow(x-1, 7) + Order(pow(x-1, 8)); + result += check_series(e, exONE(), d); + + e = pow(x + pow(x, 3), -1); + d = pow(x, -1) - x + pow(x, 3) - pow(x, 5) + Order(pow(x, 7)); + result += check_series(e, exZERO(), d); + + e = pow(pow(x, 2) + pow(x, 4), -1); + d = pow(x, -2) - 1 + pow(x, 2) - pow(x, 4) + Order(pow(x, 6)); + result += check_series(e, exZERO(), d); + + e = pow(sin(x), -2); + d = pow(x, -2) + numeric(1,3) + pow(x, 2) / 15 + pow(x, 4) * 2/189 + Order(pow(x, 5)); + result += check_series(e, exZERO(), d); + + e = sin(x) / cos(x); + d = x + pow(x, 3) / 3 + pow(x, 5) * 2/15 + pow(x, 7) * 17/315 + Order(pow(x, 8)); + result += check_series(e, exZERO(), d); + + e = cos(x) / sin(x); + d = pow(x, -1) - x / 3 - pow(x, 3) / 45 - pow(x, 5) * 2/945 + Order(pow(x, 6)); + result += check_series(e, exZERO(), d); + + e = pow(numeric(2), x); + ex t = log(ex(2)) * x; + d = 1 + t + pow(t, 2) / 2 + pow(t, 3) / 6 + pow(t, 4) / 24 + pow(t, 5) / 120 + pow(t, 6) / 720 + pow(t, 7) / 5040 + Order(pow(x, 8)); + result += check_series(e, exZERO(), d.expand()); + + e = pow(Pi, x); + t = log(Pi) * x; + d = 1 + t + pow(t, 2) / 2 + pow(t, 3) / 6 + pow(t, 4) / 24 + pow(t, 5) / 120 + pow(t, 6) / 720 + pow(t, 7) / 5040 + Order(pow(x, 8)); + result += check_series(e, exZERO(), d.expand()); + + return result; +} + +// Series addition +static unsigned series2(void) +{ + unsigned result = 0; + ex e, d; + + e = pow(sin(x), -1).series(x, exZERO(), 8) + pow(sin(-x), -1).series(x, exZERO(), 12); + d = Order(pow(x, 6)); + result += check_series(e, exZERO(), d); + + return result; +} + +// Series multiplication +static unsigned series3(void) +{ + unsigned result = 0; + ex e, d; + + e = sin(x).series(x, exZERO(), 8) * pow(sin(x), -1).series(x, exZERO(), 12); + d = 1 + Order(pow(x, 7)); + result += check_series(e, exZERO(), d); + + return result; +} + +unsigned series_expansion(void) +{ + unsigned result = 0; + + cout << "checking series expansion..." << flush; + clog << "---------series expansion:" << endl; + + result += series1(); + result += series2(); + result += series3(); + + if (!result) { + cout << " passed "; + clog << "(no output)" << endl; + } else { + cout << " failed "; + } + return result; +} diff --git a/config.h.in b/config.h.in new file mode 100644 index 00000000..a60a0fc1 --- /dev/null +++ b/config.h.in @@ -0,0 +1,58 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if lex declares yytext as a char * by default, not a char[]. */ +#undef YYTEXT_POINTER + +/* Define if you have the strdup function. */ +#undef HAVE_STRDUP + +/* Define if you have the header file. */ +#undef HAVE_CLN_CLN_H + +/* Define if you have the header file. */ +#undef HAVE_ALGORITHM + +/* Define if you have the header file. */ +#undef HAVE_IOSTREAM + +/* Define if you have the header file. */ +#undef HAVE_ITERATOR + +/* Define if you have the header file. */ +#undef HAVE_LIST + +/* Define if you have the header file. */ +#undef HAVE_MAP + +/* Define if you have the header file. */ +#undef HAVE_READLINE_HISTORY_H + +/* Define if you have the header file. */ +#undef HAVE_READLINE_READLINE_H + +/* Define if you have the header file. */ +#undef HAVE_STDEXCEPT + +/* Define if you have the header file. */ +#undef HAVE_STRING + +/* Define if you have the header file. */ +#undef HAVE_STRSTREAM + +/* Define if you have the header file. */ +#undef HAVE_TYPEINFO + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_VECTOR + +/* Define if you have the readline library (-lreadline). */ +#undef HAVE_LIBREADLINE + +/* Define if you have the stdc++ library (-lstdc++). */ +#undef HAVE_LIBSTDC__ diff --git a/configure b/configure new file mode 100755 index 00000000..2424819a --- /dev/null +++ b/configure @@ -0,0 +1,2337 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-shared build shared libraries [default=no] + (a static library will still be built as well)" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=include/ginac.h + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + + +GiNaC_Major_Version=0 +GiNaC_Minor_Version=0 +GiNaC_Micro_Version=30 +GiNaC_Version="${GiNaC_Major_Version}.${GiNaC_Minor_Version}.${GiNaC_Micro_Version}" +LibGiNaC_Ver="${GiNaC_Major_Version}:${GiNaC_Micro_Version}:${GiNaC_Minor_Version}" + +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + shared=${enableval} +else + shared="no" +fi + + +for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:550: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CXX="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CXX="$ac_cv_prog_CXX" +if test -n "$CXX"; then + echo "$ac_t""$CXX" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$CXX" && break +done +test -n "$CXX" || CXX="gcc" + + +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:582: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 + +ac_ext=C +# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cxx_cross + +cat > conftest.$ac_ext << EOF + +#line 593 "configure" +#include "confdefs.h" + +int main(){return(0);} +EOF +if { (eval echo configure:598: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cxx_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cxx_cross=no + else + ac_cv_prog_cxx_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cxx_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cxx_works" 1>&6 +if test $ac_cv_prog_cxx_works = no; then + { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:624: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 +cross_compiling=$ac_cv_prog_cxx_cross + +echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 +echo "configure:629: checking whether we are using GNU C++" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.C <&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 +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 <&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 <&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 +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 <&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 +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 <&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 +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 <&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 < +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 < +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 < +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 < +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 <&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 <&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 < +#include +#include +#include +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 +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 +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 < +#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 +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 <&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 < +/* 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 <&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 +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 <&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 <&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 <&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 </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 < 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 <> $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 <> $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 <> $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 <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + +echo "now type make" diff --git a/configure.in b/configure.in new file mode 100644 index 00000000..06a7d981 --- /dev/null +++ b/configure.in @@ -0,0 +1,101 @@ +dnl =========================================================================== +dnl Process this file with GNU Autoconf to produce a configure script. Then +dnl call ./configure to create Makefiles. After that say make and make install. +dnl See aclocal.m4 for additional self-made macros. +dnl =========================================================================== + +dnl This file is used as a signal that everything is in place: +AC_INIT(include/ginac.h) +dnl A convenient header file for some additional system-dependend output: +AC_CONFIG_HEADER(config.h) + +dnl Set the Version Number at this place only: +GiNaC_Major_Version=0 +GiNaC_Minor_Version=0 +GiNaC_Micro_Version=30 +dnl This composite variable can be inserted where it appears necessary: +GiNaC_Version="${GiNaC_Major_Version}.${GiNaC_Minor_Version}.${GiNaC_Micro_Version}" +dnl This composition is needed for libtool, if a shared lib shall be built: +LibGiNaC_Ver="${GiNaC_Major_Version}:${GiNaC_Micro_Version}:${GiNaC_Minor_Version}" + +dnl =========================================================================== +dnl Several features need to be added to standard-configure: +dnl =========================================================================== +AC_ARG_ENABLE(shared, + [ --enable-shared build shared libraries [default=no] + (a static library will still be built as well)], + shared=${enableval}, shared="no") + +dnl =========================================================================== +dnl Check for the compiler and all the utilities needed for the build: +dnl =========================================================================== +dnl Which is the C++ Compiler? (whether to use c++, g++, gcc, CC, cxx, cc++...) +AC_PROG_CXX +dnl How to run the C++ preprocessor? +AC_PROG_CXXCPP +dnl Switch to C++ language mode for the following libraries and headers: +AC_LANG_CPLUSPLUS +dnl Make sure the following libraries work by testing for symbols therein. +dnl They are automatically added the the variable $LIBS and thus passed into +dnl the Makefile: +AC_CHECK_LIB(stdc++, cout) +dnl Make sure all the necessary new-style headers are installed on the system. +dnl If one of them cannot be found the system is probably not ANSI-conform +dnl enough so trying the .h-style headers is a waste of time. +AC_CHECK_HEADERS(iostream vector map string list typeinfo iterator strstream stdexcept algorithm, , + AC_MSG_ERROR(need to have ANSI compliant headers)) +dnl We need to have Bruno Haible's CLN installed (macros are in aclocal.m4): +GINAC_CHECK_CLN_H +GINAC_CHECK_LIBCLN +dnl We need to distribure install-sh anyways since otherwise configure will +dnl refuse to do several things, like divert into subdirs and so: +AC_PROG_INSTALL +dnl Todd Brunhoff's makedepend utility is needed by make: +AC_PATH_PROG(MAKEDEPEND, makedepend, "") +dnl We need GNU libtool if the user chose to create a shared lib. (By using a +dnl little trick we can safely recycle the variable shlib which is later passed +dnl into the Makefile.) +case "${shared}" in +"yes"|"Yes"|"YES") # Default-enable ("yes") or user was nitpicking: + shared="shlib"; + AC_PATH_PROG(LIBTOOL, libtool, "") + if test "${LIBTOOL}" == ""; then + AC_MSG_WARN([libtool not found: building static lib only]) + shared=""; + fi + ;; +*) # Default, default-disable ("no") or user entered bogus: + shared=""; + ;; +esac +dnl Check for helpers needed for building the GiNaC interactive shell: +AC_PROG_LEX +AC_PROG_YACC +AC_DECL_YYTEXT +AC_HEADER_STDC +AC_CHECK_HEADERS(unistd.h) +AC_CHECK_FUNCS(strdup) +AC_CHECK_HEADERS(readline/readline.h readline/history.h, , AC_MSG_ERROR(need to have GNU readline headers)) +AC_CHECK_LIB(readline, readline, , AC_MSG_ERROR(need to have GNU readline library)) +dnl Check for utilities needed by the different kinds of documentation. +dnl Documantation needs only be built when extending it, so never mind if it +dnl cannot find those helpers: +AC_PATH_PROG(DOXYGEN, doxygen, "") +AC_PATH_PROG(LATEX, latex, "") +AC_PATH_PROG(MAKEINDEX, makeindex, "") +AC_PATH_PROG(DVIPS, dvips, "") +AC_PATH_PROG(FIG2DEV, fig2dev, "") +AC_PATH_PROG(JADE, jade, "") +AC_PATH_PROG(JADETEX, jadetex, "") + +dnl =========================================================================== +dnl Substitute these variables in the Makefile: +dnl =========================================================================== +AC_SUBST(shared) +AC_SUBST(LibGiNaC_Ver) + +dnl =========================================================================== +dnl Produce a Makefile from Makefile.in: +dnl =========================================================================== +AC_OUTPUT([Makefile src/Makefile check/Makefile ginsh/Makefile doc/Makefile]) +echo "now type make" diff --git a/doc/DoxyfileHTML b/doc/DoxyfileHTML new file mode 100644 index 00000000..fefa2535 --- /dev/null +++ b/doc/DoxyfileHTML @@ -0,0 +1,371 @@ +# Doxyfile 0.49-990522 +# This file describes the settings to be used by doxygen for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of word surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = GiNaC + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ./doc + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: Dutch + +OUTPUT_LANGUAGE = English + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# If the EXTRACT_ALL tag is set to YES all classes and functions will be +# included in the documentation, even if no documentation was available. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members inside documented classes or files. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSESS tag is set to YES, Doxygen will hide all +# undocumented classes. + +HIDE_UNDOC_CLASSES = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the FULL_PATH_NAMES tag is set to YES Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user defined part of the path. Stripping is +# only done if the specified string matches the left-hand part of the path. + +STRIP_FROM_PATH = + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a class diagram (in Html and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. + +CLASS_DIAGRAMS = YES + +# If the CASE_SENSE_NAMES tag is set to NO (the default) then Doxygen +# will only generate file names in lower case letters. If set to +# YES upper case letters are also allowed. This is useful if you have +# classes or files whose names only differ in case and if your file system +# supports case sensitive file names. + +CASE_SENSE_NAMES = YES + +# If the VERBATIM_HEADERS tag is set the YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ./ + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +FILE_PATTERNS = *.cpp *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = reference + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = ./doc/Doxyfooter.html + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. + +MACRO_EXPANSION = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = ./ + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED tag. + +EXPAND_ONLY_PREDEF = NO + +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + +# The CGI_NAME tag should be the name of the CGI script that +# starts the search engine (doxysearch) with the correct parameters. +# A script with this name will be generated by doxygen. + +CGI_NAME = search.cgi + +# The CGI_URL tag should be the absolute URL to the directory where the +# cgi binaries are located. See the documentation of your http daemon for +# details. + +CGI_URL = + +# The DOC_URL tag should be the absolute URL to the directory where the +# documentation is located. If left blank the absolute path to the +# documentation, with file:// prepended to it, will be used. + +DOC_URL = + +# The DOC_ABSPATH tag should be the absolute path to the directory where the +# documentation is located. If left blank the directory on the local machine +# will be used. + +DOC_ABSPATH = + +# The BIN_ABSPATH tag must point to the directory where the doxysearch binary +# is installed. + +BIN_ABSPATH = /usr/local/bin/ + +# The EXT_DOC_PATHS tag can be used to specify one or more paths to +# documentation generated for other projects. This allows doxysearch to search +# the documentation for these projects as well. + +EXT_DOC_PATHS = diff --git a/doc/DoxyfileTEX b/doc/DoxyfileTEX new file mode 100644 index 00000000..670ca239 --- /dev/null +++ b/doc/DoxyfileTEX @@ -0,0 +1,371 @@ +# Doxyfile 0.49-990522 +# This file describes the settings to be used by doxygen for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of word surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = GiNaC + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ./doc + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: Dutch + +OUTPUT_LANGUAGE = English + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# If the EXTRACT_ALL tag is set to YES all classes and functions will be +# included in the documentation, even if no documentation was available. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members inside documented classes or files. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSESS tag is set to YES, Doxygen will hide all +# undocumented classes. + +HIDE_UNDOC_CLASSES = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the FULL_PATH_NAMES tag is set to YES Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user defined part of the path. Stripping is +# only done if the specified string matches the left-hand part of the path. + +STRIP_FROM_PATH = + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a class diagram (in Html and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. + +CLASS_DIAGRAMS = YES + +# If the CASE_SENSE_NAMES tag is set to NO (the default) then Doxygen +# will only generate file names in lower case letters. If set to +# YES upper case letters are also allowed. This is useful if you have +# classes or files whose names only differ in case and if your file system +# supports case sensitive file names. + +CASE_SENSE_NAMES = YES + +# If the VERBATIM_HEADERS tag is set the YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ./ + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +FILE_PATTERNS = *.cpp *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output + +GENERATE_HTML = NO + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = reference + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = ./doc/Doxyfooter.html + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. + +MACRO_EXPANSION = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = ./ + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED tag. + +EXPAND_ONLY_PREDEF = NO + +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + +# The CGI_NAME tag should be the name of the CGI script that +# starts the search engine (doxysearch) with the correct parameters. +# A script with this name will be generated by doxygen. + +CGI_NAME = search.cgi + +# The CGI_URL tag should be the absolute URL to the directory where the +# cgi binaries are located. See the documentation of your http daemon for +# details. + +CGI_URL = + +# The DOC_URL tag should be the absolute URL to the directory where the +# documentation is located. If left blank the absolute path to the +# documentation, with file:// prepended to it, will be used. + +DOC_URL = + +# The DOC_ABSPATH tag should be the absolute path to the directory where the +# documentation is located. If left blank the directory on the local machine +# will be used. + +DOC_ABSPATH = + +# The BIN_ABSPATH tag must point to the directory where the doxysearch binary +# is installed. + +BIN_ABSPATH = /usr/local/bin/ + +# The EXT_DOC_PATHS tag can be used to specify one or more paths to +# documentation generated for other projects. This allows doxysearch to search +# the documentation for these projects as well. + +EXT_DOC_PATHS = diff --git a/doc/Doxyfooter.html b/doc/Doxyfooter.html new file mode 100644 index 00000000..b63e6e6b --- /dev/null +++ b/doc/Doxyfooter.html @@ -0,0 +1,9 @@ +
+This page is part of the GiNaC +developer's reference. It was generated automatically by doxygen. For +an introduction, see the tutorial. + + + diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 00000000..66acd0f5 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,169 @@ +# Generated automatically from Makefile.in by configure. +# This is the prototype Makefile for all of GiNaC's documentation. It tries to +# be tolerant---if some tools were not found it skips the built of that part +# of documentation and tries to continue. + +# Substitution variables from configure skript: +# Here come the usual install directories in GNU-configure fashion: +prefix = /usr/local +docdir = ${prefix}/share/doc/GiNaC +srcdir = . +# Dimitri van Heesch's Doxygen is needed for developer's resource: +DOXYGEN = /usr/local/bin_i386/doxygen +# LaTeX and friends are needed for processing developer's resource for print: +LATEX = /usr/local/bin/latex +MAKEINDEX = /usr/local/bin/makeindex +DVIPS = /usr/local/bin/dvips +FIG2DEV = /usr/bin/X11/fig2dev +# Jade and friends needed for generating the tutorial: +JADE = /usr/bin/jade +JADETEX = /usr/local/bin/jadetex +# Arguments for Jade and friends (does anybody know how to find them out?) +# JADEARGS_TEX = -t tex -o tutorial.tex -d /usr/lib/dsssl/stylesheets/docbook/print/docbook.dsl +JADEARGS_TEX = -t tex -o tutorial.tex -d /usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/print/docbook.dsl +# JADEARGS_HTML = -t sgml -d /usr/lib/dsssl/stylesheets/docbook/html/docbook.dsl +JADEARGS_HTML = -t sgml -d /usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/html/docbook.dsl +# Autoconf macro AC_PROC_INSTALL sets these: +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +# All LaTeX builds will take place in a separate subdirectory: +VPATH = .:./latex:./tutorial + +# default target: +all: reference tutorial + +# REFERENCE: +# This section produces HTML'ed and TeX'ed developer's reference from the +# sources with a JavaDoc-like tool (in this case doxygen): +reference_html: + @ if [ ! -d ${srcdir}/reference ]; then mkdir ${srcdir}/reference; fi + @ if [ "${DOXYGEN}" ]; then \ + echo "Running ${DOXYGEN} ./DoxyfileHTML..."; \ + cd ..; ${DOXYGEN} ./doc/DoxyfileHTML; \ + else \ + echo "warning: target reference_html disabled by configuration"; \ + fi + +reference.tex: + @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi + @ if [ "${DOXYGEN}" ]; then \ + echo "Running ${DOXYGEN} ./DoxyfileTEX..."; \ + cd ..; ${DOXYGEN} ./doc/DoxyfileTEX; \ + else \ + echo "warning: target reference.tex disabled by configuration"; \ + fi + - mv ${srcdir}/latex/refman.tex ${srcdir}/latex/reference.tex + +reference.dvi: reference.tex + @ if [ "${LATEX}" -a "${MAKEINDEX}" ]; then \ + cd latex; \ + ${LATEX} reference.tex && \ + ${MAKEINDEX} reference.idx && \ + ${LATEX} reference.tex; \ + else \ + echo "warning: target reference.dvi disabled by configuration"; \ + fi + +reference.ps: reference.dvi + @ if [ "${DVIPS}" ]; then \ + echo "Running ${DVIPS} -o reference.ps reference.dvi..."; \ + cd latex; ${DVIPS} -o reference.ps reference.dvi; \ + else \ + echo "warning: target reference.ps disabled by configuration"; \ + fi + +reference: reference_html reference.ps + +# TUTORIAL: +# This section produces HTML'ed and TeX'ed versions of the tutorial using a +# SGML to TeX converter (in this case jade). As a dirty hack, we are doing +# some regexpese to tutorial.sgml prior to parsing it, in order to allow for +# different graphics output. This seems to be an ugly limitation of docbook... + +EPS = classhierarchy.eps rep_naive.eps rep_pair.eps +PNG = classhierarchy.png rep_naive.png rep_pair.png + +tutorial/index.html: tutorial.sgml.in ${PNG} + @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi + @ if [ "${JADE}" ]; then \ + sed -e 's/graext/png/g' -e 's/GRAEXT/GIF/g' tutorial.sgml.in > tutorial.sgml; \ + echo "Running ${JADE} ${JADEARGS_HTML} tutorial.sgml..."; \ + cd tutorial/; ${JADE} ${JADEARGS_HTML} ../tutorial.sgml; \ + if [ -f book1.html ]; then cp book1.html index.html; fi; \ + else \ + echo "warning: target tutorial_html disabled by configuration"; \ + fi + +tutorial.tex: tutorial.sgml.in ${EPS} + @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi + @ if [ "${JADE}" -a "${LATEX}" ]; then \ + sed -e 's/graext/eps/g' -e 's/GRAEXT/EPS/g' tutorial.sgml.in > tutorial.sgml; \ + echo "Running ${JADE} ${JADEARGS_TEX} tutorial.sgml..."; \ + cd latex; ${JADE} ${JADEARGS_TEX} ../tutorial.sgml ; \ + else \ + echo "warning: target tutorial.tex disabled by configuration"; \ + fi + +tutorial.dvi: tutorial.tex + @ if [ "${JADETEX}" ]; then \ + echo "Running ${JADETEX} tutorial.tex..."; \ + cd latex; ${JADETEX} tutorial.tex && ${JADETEX} tutorial.tex && ${JADETEX} tutorial.tex; \ + else \ + echo "warning: target tutorial.dvi disabled by configuration"; \ + fi + +tutorial.ps: tutorial.dvi + @ if [ "${DVIPS}" ]; then \ + echo "Running ${DVIPS} tutorial.dvi -o tutorial.ps..."; \ + cd latex; ${DVIPS} tutorial.dvi -o tutorial.ps; \ + else \ + echo "warning: target tutorial.ps disabled by configuration"; \ + fi + +tutorial: tutorial/index.html tutorial.ps + +# Target for installing all generated documentation files on the system. +# (Foolproof: installs what we got, even if one or more targets failed.) +install: + - ${INSTALL} -d ${docdir}/reference/ + - ${INSTALL_DATA} ${srcdir}/reference/* ${docdir}/reference/ + - ${INSTALL_DATA} ${srcdir}/latex/reference.ps ${docdir}/ + - ${INSTALL} -d ${docdir}/tutorial/ + - ${INSTALL_DATA} ${srcdir}/tutorial/* ${docdir}/tutorial/ + - ${INSTALL_DATA} ${srcdir}/latex/tutorial.ps ${docdir}/ + +# Removes all installed documentation files from the system: +uninstall: + rm -rf ${docdir} + +# The next targets should only be called in case of emergency by developers, +# since the complete documentation is not normally rebuilt. In any case, they +# should only be called from people who know what they are doing and never +# from top-level Makefile's targets clean and distclean. +clean: + rm -rf ${srcdir}/tutorial ${srcdir}/reference ${srcdir}/latex + rm -f tutorial.sgml + +distclean: clean + rm -f Makefile + +# Special dummy targets: +.SUFFIXES: .fig .eps .png +.PHONY: all clean distclean reference tutorial +.SILENT: all reference tutorial_html tutorial_tex + +# Suffix rules: +.fig.eps : + @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi + if [ "${FIG2DEV}" ]; then \ + ${FIG2DEV} -L ps -m 0.8 $< ${srcdir}/latex/$@; \ + else \ + echo "warning: fig2dev was not found by configure"; \ + fi +.fig.png : + @ if [ ! -d ${srcdir}/tutorial ]; then mkdir ${srcdir}/tutorial; fi + if [ "${FIG2DEV}" ]; then \ + ${FIG2DEV} -L png $< ${srcdir}/tutorial/$@; \ + else \ + echo "warning: fig2dev was not found by configure"; \ + fi diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 00000000..ebe33f69 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,168 @@ +# This is the prototype Makefile for all of GiNaC's documentation. It tries to +# be tolerant---if some tools were not found it skips the built of that part +# of documentation and tries to continue. + +# Substitution variables from configure skript: +# Here come the usual install directories in GNU-configure fashion: +prefix = @prefix@ +docdir = @datadir@/doc/GiNaC +srcdir = @srcdir@ +# Dimitri van Heesch's Doxygen is needed for developer's resource: +DOXYGEN = @DOXYGEN@ +# LaTeX and friends are needed for processing developer's resource for print: +LATEX = @LATEX@ +MAKEINDEX = @MAKEINDEX@ +DVIPS = @DVIPS@ +FIG2DEV = @FIG2DEV@ +# Jade and friends needed for generating the tutorial: +JADE = @JADE@ +JADETEX = @JADETEX@ +# Arguments for Jade and friends (does anybody know how to find them out?) +# JADEARGS_TEX = -t tex -o tutorial.tex -d /usr/lib/dsssl/stylesheets/docbook/print/docbook.dsl +JADEARGS_TEX = -t tex -o tutorial.tex -d /usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/print/docbook.dsl +# JADEARGS_HTML = -t sgml -d /usr/lib/dsssl/stylesheets/docbook/html/docbook.dsl +JADEARGS_HTML = -t sgml -d /usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/html/docbook.dsl +# Autoconf macro AC_PROC_INSTALL sets these: +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +# All LaTeX builds will take place in a separate subdirectory: +VPATH = @srcdir@:@srcdir@/latex:@srcdir@/tutorial + +# default target: +all: reference tutorial + +# REFERENCE: +# This section produces HTML'ed and TeX'ed developer's reference from the +# sources with a JavaDoc-like tool (in this case doxygen): +reference_html: + @ if [ ! -d ${srcdir}/reference ]; then mkdir ${srcdir}/reference; fi + @ if [ "${DOXYGEN}" ]; then \ + echo "Running ${DOXYGEN} ./DoxyfileHTML..."; \ + cd ..; ${DOXYGEN} ./doc/DoxyfileHTML; \ + else \ + echo "warning: target reference_html disabled by configuration"; \ + fi + +reference.tex: + @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi + @ if [ "${DOXYGEN}" ]; then \ + echo "Running ${DOXYGEN} ./DoxyfileTEX..."; \ + cd ..; ${DOXYGEN} ./doc/DoxyfileTEX; \ + else \ + echo "warning: target reference.tex disabled by configuration"; \ + fi + - mv ${srcdir}/latex/refman.tex ${srcdir}/latex/reference.tex + +reference.dvi: reference.tex + @ if [ "${LATEX}" -a "${MAKEINDEX}" ]; then \ + cd latex; \ + ${LATEX} reference.tex && \ + ${MAKEINDEX} reference.idx && \ + ${LATEX} reference.tex; \ + else \ + echo "warning: target reference.dvi disabled by configuration"; \ + fi + +reference.ps: reference.dvi + @ if [ "${DVIPS}" ]; then \ + echo "Running ${DVIPS} -o reference.ps reference.dvi..."; \ + cd latex; ${DVIPS} -o reference.ps reference.dvi; \ + else \ + echo "warning: target reference.ps disabled by configuration"; \ + fi + +reference: reference_html reference.ps + +# TUTORIAL: +# This section produces HTML'ed and TeX'ed versions of the tutorial using a +# SGML to TeX converter (in this case jade). As a dirty hack, we are doing +# some regexpese to tutorial.sgml prior to parsing it, in order to allow for +# different graphics output. This seems to be an ugly limitation of docbook... + +EPS = classhierarchy.eps rep_naive.eps rep_pair.eps +PNG = classhierarchy.png rep_naive.png rep_pair.png + +tutorial/index.html: tutorial.sgml.in ${PNG} + @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi + @ if [ "${JADE}" ]; then \ + sed -e 's/graext/png/g' -e 's/GRAEXT/GIF/g' tutorial.sgml.in > tutorial.sgml; \ + echo "Running ${JADE} ${JADEARGS_HTML} tutorial.sgml..."; \ + cd tutorial/; ${JADE} ${JADEARGS_HTML} ../tutorial.sgml; \ + if [ -f book1.html ]; then cp book1.html index.html; fi; \ + else \ + echo "warning: target tutorial_html disabled by configuration"; \ + fi + +tutorial.tex: tutorial.sgml.in ${EPS} + @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi + @ if [ "${JADE}" -a "${LATEX}" ]; then \ + sed -e 's/graext/eps/g' -e 's/GRAEXT/EPS/g' tutorial.sgml.in > tutorial.sgml; \ + echo "Running ${JADE} ${JADEARGS_TEX} tutorial.sgml..."; \ + cd latex; ${JADE} ${JADEARGS_TEX} ../tutorial.sgml ; \ + else \ + echo "warning: target tutorial.tex disabled by configuration"; \ + fi + +tutorial.dvi: tutorial.tex + @ if [ "${JADETEX}" ]; then \ + echo "Running ${JADETEX} tutorial.tex..."; \ + cd latex; ${JADETEX} tutorial.tex && ${JADETEX} tutorial.tex && ${JADETEX} tutorial.tex; \ + else \ + echo "warning: target tutorial.dvi disabled by configuration"; \ + fi + +tutorial.ps: tutorial.dvi + @ if [ "${DVIPS}" ]; then \ + echo "Running ${DVIPS} tutorial.dvi -o tutorial.ps..."; \ + cd latex; ${DVIPS} tutorial.dvi -o tutorial.ps; \ + else \ + echo "warning: target tutorial.ps disabled by configuration"; \ + fi + +tutorial: tutorial/index.html tutorial.ps + +# Target for installing all generated documentation files on the system. +# (Foolproof: installs what we got, even if one or more targets failed.) +install: + - ${INSTALL} -d ${docdir}/reference/ + - ${INSTALL_DATA} ${srcdir}/reference/* ${docdir}/reference/ + - ${INSTALL_DATA} ${srcdir}/latex/reference.ps ${docdir}/ + - ${INSTALL} -d ${docdir}/tutorial/ + - ${INSTALL_DATA} ${srcdir}/tutorial/* ${docdir}/tutorial/ + - ${INSTALL_DATA} ${srcdir}/latex/tutorial.ps ${docdir}/ + +# Removes all installed documentation files from the system: +uninstall: + rm -rf ${docdir} + +# The next targets should only be called in case of emergency by developers, +# since the complete documentation is not normally rebuilt. In any case, they +# should only be called from people who know what they are doing and never +# from top-level Makefile's targets clean and distclean. +clean: + rm -rf ${srcdir}/tutorial ${srcdir}/reference ${srcdir}/latex + rm -f tutorial.sgml + +distclean: clean + rm -f Makefile + +# Special dummy targets: +.SUFFIXES: .fig .eps .png +.PHONY: all clean distclean reference tutorial +.SILENT: all reference tutorial_html tutorial_tex + +# Suffix rules: +.fig.eps : + @ if [ ! -d ${srcdir}/latex ]; then mkdir ${srcdir}/latex; fi + if [ "${FIG2DEV}" ]; then \ + ${FIG2DEV} -L ps -m 0.8 $< ${srcdir}/latex/$@; \ + else \ + echo "warning: fig2dev was not found by configure"; \ + fi +.fig.png : + @ if [ ! -d ${srcdir}/tutorial ]; then mkdir ${srcdir}/tutorial; fi + if [ "${FIG2DEV}" ]; then \ + ${FIG2DEV} -L png $< ${srcdir}/tutorial/$@; \ + else \ + echo "warning: fig2dev was not found by configure"; \ + fi diff --git a/doc/classhierarchy.fig b/doc/classhierarchy.fig new file mode 100644 index 00000000..fef6907d --- /dev/null +++ b/doc/classhierarchy.fig @@ -0,0 +1,117 @@ +#FIG 3.2 +Landscape +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +5 1 1 2 0 7 100 0 -1 4.000 0 0 1 0 1896.500 2807.128 791 579 1973 321 3002 579 + 1 1 1.00 68.57 137.14 +6 4853 2533 5779 2790 +2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5 + 4853 2533 5779 2533 5779 2790 4853 2790 4853 2533 +4 1 0 99 0 0 14 0.0000 4 150 555 5316 2739 matrix\001 +-6 +6 4853 2070 5779 2327 +2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5 + 4853 2070 5779 2070 5779 2327 4853 2327 4853 2070 +4 1 0 99 0 0 14 0.0000 4 150 705 5316 2276 numeric\001 +-6 +6 4853 1607 5779 1864 +2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5 + 4853 1607 5779 1607 5779 1864 4853 1864 4853 1607 +4 1 0 99 0 0 14 0.0000 4 135 735 5316 1813 constant\001 +-6 +6 585 2019 1099 2276 +2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5 + 585 2019 1099 2019 1099 2276 585 2276 585 2019 +4 1 0 99 0 0 14 0.0000 4 150 315 842 2224 add\001 +-6 +6 1511 2019 2025 2276 +2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5 + 1511 2019 2025 2019 2025 2276 1511 2276 1511 2019 +4 1 0 99 0 0 14 0.0000 4 150 315 1768 2224 mul\001 +-6 +6 996 1144 2025 1401 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 2025 1144 996 1144 996 1401 2025 1401 2025 1144 +4 1 0 99 0 0 14 0.0000 4 195 840 1511 1350 expairseq\001 +-6 +6 3053 630 3876 887 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 3053 630 3876 630 3876 887 3053 887 3053 630 +4 1 0 99 0 0 14 0.0000 4 150 450 3465 836 basic\001 +-6 +6 225 463 739 720 +2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5 + 225 463 739 463 739 720 225 720 225 463 +4 1 0 99 0 0 14 0.0000 4 105 210 482 668 ex\001 +-6 +6 2160 1498 2880 1755 +2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5 + 2160 1498 2880 1498 2880 1755 2160 1755 2160 1498 +4 1 0 99 0 0 14 0.0000 4 150 555 2520 1704 power\001 +-6 +6 2475 1935 3330 2205 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 2475 1948 3330 1948 3330 2205 2475 2205 2475 1948 +4 1 0 99 0 0 14 0.0000 4 150 690 2899 2154 exprseq\001 +-6 +6 2250 2925 3195 3195 +2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5 + 2250 2925 3195 2925 3195 3195 2250 3195 2250 2925 +4 1 0 99 0 0 14 0.0000 4 150 690 2719 3131 function\001 +-6 +6 1626 2533 2449 2790 +2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5 + 1626 2533 2449 2533 2449 2790 1626 2790 1626 2533 +4 1 0 99 0 0 14 0.0000 4 150 525 2038 2739 ncmul\001 +-6 +6 3060 2385 3780 2655 +2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5 + 3060 2385 3780 2385 3780 2655 3060 2655 3060 2385 +4 1 0 99 0 0 14 0.0000 4 150 510 3394 2591 series\001 +-6 +6 4860 1119 5786 1376 +2 2 0 1 0 3 100 0 20 0.000 0 0 -1 0 0 5 + 4860 1119 5786 1119 5786 1376 4860 1376 4860 1119 +4 1 0 99 0 0 14 0.0000 4 195 615 5323 1324 symbol\001 +-6 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2 + 1 1 1.00 60.00 120.00 + 3825 945 4802 2121 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2 + 1 1 1.00 60.00 120.00 + 3053 939 2076 1144 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2 + 1 1 1.00 60.00 120.00 + 3156 939 2693 1453 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2 + 1 1 1.00 60.00 120.00 + 3722 939 4802 2584 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2 + 1 1 1.00 60.00 120.00 + 3915 945 4815 1665 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2 + 1 1 1.00 60.00 120.00 + 3208 939 3105 1916 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2 + 1 1 1.00 60.00 120.00 + 2693 2276 2231 2481 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2 + 1 1 1.00 60.00 120.00 + 3371 937 3465 2340 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2 + 1 1 1.00 60.00 120.00 + 2825 2282 2677 2886 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2 + 1 1 1.00 60.00 120.00 + 1459 1453 894 1967 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2 + 1 1 1.00 60.00 120.00 + 1562 1453 1716 1967 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 1 2 + 1 1 1.00 60.00 120.00 + 3915 881 4815 1215 diff --git a/doc/powerlaws.tex b/doc/powerlaws.tex new file mode 100644 index 00000000..75ce8c92 --- /dev/null +++ b/doc/powerlaws.tex @@ -0,0 +1,155 @@ +\documentclass{article} + +\begin{document} + +\section{Power Laws} + +\subsection{Definitions} + +Definitions for power and log: +\begin{equation} +x^a \equiv e^{a \ln x} +\end{equation} +\begin{equation} +\ln x \equiv \ln |x| + i \arg(x) \mbox{ where } -\pi < \arg(x) \le \pi +\end{equation} + +\subsection{General rules} + +\begin{equation} +e^x e^y = e^{x+y} +\end{equation} +for arbitrary complex $x$ and $y$ + +\begin{equation} +x^{-a} = \frac{1}{x^a} +\end{equation} +for arbitrary complex $x$ and $a$ + +\subsection{$(ax)^b=a^b x^b$} + +\subsubsection{$b$ integer, $x$ and $a$ arbitrary complex} + +assume $b>0$ + +\begin{eqnarray} +(ax)^b & = & \underbrace{(ax) \cdots (ax)}_{b \times} +\nonumber\\ +& = & \underbrace{a \cdots a}_{b \times} + \underbrace{x \cdots x}_{b \times} +\nonumber\\ +& = & a^b x^b \mbox{ q.e.d.} +\end{eqnarray} + +if $b<0$ (so $b=-|b|$) +\begin{eqnarray} +(ax)^b & = & \frac{1}{(ax)^{|b|}} +\nonumber\\ +& = & \frac{1}{a^{|b|} x^{|b|}} +\nonumber\\ +& = & a^{-|b|} x^{-|b|} +\nonumber\\ +& = & a^b x^b +\end{eqnarray} + +\subsubsection{$a>0$, $x$ and $b$ arbitrary complex} + +\begin{eqnarray} +(ax)^b & = & e^{b \ln(ax)} +\nonumber\\ +& = & e^{b (\ln |ax| + i \arg(ax))} +\end{eqnarray} + +if $a$ is real and positive: +\begin{equation} +\ln |ax| = \ln |a| + \ln |x| = \ln a + \ln |x| +\end{equation} +and +\begin{equation} +\arg(ax) = \arg(x) +\end{equation} + +So +\begin{eqnarray} +e^{b (\ln |ax| + i \arg(ax))} & = & +e^{b (\ln a + \ln |x| + i \arg(x))} +\nonumber\\ +& = & e^{b (\ln a + \ln x)} +\nonumber\\ +& = & e^{b \ln a} e^{b \ln x} +\nonumber\\ +& = & a^b x^b \mbox{ q.e.d.} +\end{eqnarray} + +\subsection{$(x^a)^b = x^{ab}$} + +\subsubsection{$b$ integer, $x$ and $a$ arbitrary complex} + +assume $b>0$ + +\begin{eqnarray} +(x^a)^b & = & \underbrace{(x^a) \cdots (x^a)}_{b \times} +\nonumber\\ +& = & \underbrace{e^{a \ln x} \cdots e^{a \ln x}}_{b \times} +\nonumber\\ +& = & e^{\underbrace{\scriptstyle a \ln x + \dots + a \ln x}_{b \times}} +\nonumber\\ +& = & e^{a b \ln x} +\nonumber\\ +& = & x^{ab} \mbox{ q.e.d.} +\end{eqnarray} + +if $b<0$ (so $b=-|b|$) +\begin{eqnarray} +(x^a)^b & = & \frac{1}{(x^a)^{|b|}} +\nonumber\\ +& = & \frac{1}{x^{a|b|}} +\nonumber\\ +& = & x^{-a|b|} +\nonumber\\ +& = & x^{ab} +\end{eqnarray} + +\subsubsection{$-1 < a \le 1$, $x$ and $b$ arbitrary complex} + +We have +\begin{equation} +x^a=e^{a \ln|x| + ia\arg(x)} +\end{equation} +if $a$ is real +\begin{equation} +|x^a|=e^{a\ln|x|} +\end{equation} +and +\begin{equation} +\arg(x^a)-a\arg(x)=2k\pi +\end{equation} +now if $-1 < a \le 1$, then $-\pi < a\arg(x) \le \pi$, +and so $k=0$, i.e. +\begin{equation} +\arg(x^a)=a\arg(x) +\end{equation} +(Note that for $a=-1$ this may not be true, as $-1 \arg(x)$ may be equal to $-\pi$.) +So +\begin{eqnarray} +\ln(x^a) & = & \ln|x^a| + i\arg(x^a) +\nonumber\\ +& = & \ln (e^{a\ln|x|})+ia\arg(x) +\nonumber\\ +& = & a \ln |x| + ia\arg(x) \mbox{ (because $a\ln|x|$ is real)} +\nonumber\\ +& = & a\ln x +\end{eqnarray} +Hence +\begin{eqnarray} +(x^a)^b & = & e^{b\ln x^a} +\nonumber\\ +& = & e^{ba\ln x} +\nonumber\\ +& = & x^{ab} \mbox{ q.e.d.} +\end{eqnarray} + +proof contributed by Adam Strzebonski from Wolfram Research +({\tt adams@wolfram.com}) in newsgroup {\tt sci.math.symbolic}. + +\end{document} \ No newline at end of file diff --git a/doc/rep_naive.fig b/doc/rep_naive.fig new file mode 100644 index 00000000..63292a1e --- /dev/null +++ b/doc/rep_naive.fig @@ -0,0 +1,104 @@ +#FIG 3.2 +Landscape +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +6 1530 3330 1890 3690 +1 3 0 1 0 7 100 0 20 0.000 1 0.0000 1725 3525 165 165 1725 3525 1890 3520 +4 1 0 99 0 0 14 0.0000 4 105 105 1725 3595 a\001 +-6 +6 2520 4005 2880 4365 +1 3 0 1 0 7 100 0 20 0.000 1 0.0000 2715 4200 165 165 2715 4200 2880 4195 +4 1 0 99 0 0 14 0.0000 4 150 105 2715 4270 2\001 +-6 +6 2970 4005 3330 4365 +1 3 0 1 0 7 100 0 20 0.000 1 0.0000 3165 4200 165 165 3165 4200 3330 4195 +4 1 0 99 0 0 14 0.0000 4 150 105 3165 4270 b\001 +-6 +6 3870 4005 4230 4365 +1 3 0 1 0 7 100 0 20 0.000 1 0.0000 4065 4200 165 165 4065 4200 4230 4195 +4 1 0 99 0 0 14 0.0000 4 150 240 4065 4270 -1\001 +-6 +6 4320 4005 4680 4365 +1 3 0 1 0 7 100 0 20 0.000 1 0.0000 4515 4200 165 165 4515 4200 4680 4195 +4 1 0 99 0 0 14 0.0000 4 105 105 4515 4270 c\001 +-6 +6 2610 2700 3240 3060 +6 2610 2700 3240 2970 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 2610 2700 3240 2700 3240 2970 2610 2970 2610 2700 +4 1 0 99 0 0 14 0.0000 4 150 315 2925 2906 add\001 +-6 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 2610 2970 3240 2970 3240 3060 2610 3060 2610 2970 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 2610 2970 2820 2970 2820 3060 2610 3060 2610 2970 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 3030 2970 3240 2970 3240 3060 3030 3060 3030 2970 +-6 +6 2610 3375 3240 3735 +6 2610 3375 3240 3645 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 2610 3375 3240 3375 3240 3645 2610 3645 2610 3375 +4 1 0 99 0 0 14 0.0000 4 150 315 2925 3581 mul\001 +-6 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 2610 3645 3240 3645 3240 3735 2610 3735 2610 3645 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2 + 2925 3645 2925 3735 +-6 +6 3960 3375 4590 3735 +6 3960 3375 4590 3645 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 3960 3375 4590 3375 4590 3645 3960 3645 3960 3375 +4 1 0 99 0 0 14 0.0000 4 150 315 4275 3581 mul\001 +-6 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 3960 3645 4590 3645 4590 3735 3960 3735 3960 3645 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2 + 4275 3645 4275 3735 +-6 +6 1260 2025 1890 2385 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 1260 2025 1890 2025 1890 2295 1260 2295 1260 2025 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 1260 2295 1890 2295 1890 2385 1260 2385 1260 2295 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 0 0 2 + 1575 2385 1575 2295 +4 1 0 99 0 0 14 0.0000 4 150 315 1575 2231 mul\001 +-6 +6 225 2685 555 3015 +1 3 0 1 0 7 100 0 20 0.000 1 0.0000 390 2850 165 165 390 2850 555 2845 +4 1 0 99 0 0 14 0.0000 4 150 105 390 2920 d\001 +-6 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2700 3060 1845 3375 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2925 3060 2925 3375 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3150 3060 4005 3375 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 1799 2387 2654 2702 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 1350 2385 495 2700 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2790 3735 2745 4005 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3075 3733 3120 4003 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 4133 3734 4088 4004 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 4387 3732 4432 4002 diff --git a/doc/rep_pair.fig b/doc/rep_pair.fig new file mode 100644 index 00000000..7160eeff --- /dev/null +++ b/doc/rep_pair.fig @@ -0,0 +1,98 @@ +#FIG 3.2 +Landscape +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +6 1260 135 1890 585 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 1260 135 1890 135 1890 405 1260 405 1260 135 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 1260 405 1890 405 1890 495 1260 495 1260 405 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 1260 495 1890 495 1890 585 1260 585 1260 495 +2 1 0 1 0 7 99 0 -1 0.000 0 0 -1 0 0 2 + 1575 585 1575 405 +4 1 0 99 0 0 14 0.0000 4 150 315 1575 341 mul\001 +-6 +6 2610 900 3240 1170 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 2610 900 3240 900 3240 1170 2610 1170 2610 900 +4 1 0 99 0 0 14 0.0000 4 150 315 2925 1106 add\001 +-6 +6 2610 1260 3240 1350 +2 2 0 1 0 7 99 0 20 0.000 0 0 -1 0 0 5 + 2610 1260 2820 1260 2820 1350 2610 1350 2610 1260 +2 2 0 1 0 7 99 0 20 0.000 0 0 -1 0 0 5 + 3030 1260 3240 1260 3240 1350 3030 1350 3030 1260 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 2610 1260 3240 1260 3240 1350 2610 1350 2610 1260 +-6 +6 2610 1170 3240 1260 +2 2 0 1 0 7 99 0 20 0.000 0 0 -1 0 0 5 + 2610 1170 2820 1170 2820 1260 2610 1260 2610 1170 +2 2 0 1 0 7 99 0 20 0.000 0 0 -1 0 0 5 + 3030 1170 3240 1170 3240 1260 3030 1260 3030 1170 +2 2 0 1 0 7 100 0 20 0.000 0 0 -1 0 0 5 + 2610 1170 3240 1170 3240 1260 2610 1260 2610 1170 +-6 +6 225 900 585 1710 +6 225 930 555 1260 +1 3 0 1 0 7 100 0 20 0.000 1 0.0000 390 1095 165 165 390 1095 555 1090 +4 1 0 99 0 0 14 0.0000 4 150 105 390 1165 d\001 +-6 +6 225 1350 585 1710 +1 3 0 1 0 7 100 0 20 0.000 1 0.0000 390 1545 165 165 390 1545 555 1540 +4 1 0 99 0 0 14 0.0000 4 150 105 390 1615 1\001 +-6 +-6 +6 1575 2115 1935 2475 +1 3 0 1 0 7 100 0 20 0.000 1 0.0000 1740 2310 165 165 1740 2310 1905 2305 +4 1 0 99 0 0 14 0.0000 4 150 105 1740 2380 1\001 +-6 +6 1575 1665 1935 2025 +1 3 0 1 0 7 100 0 20 0.000 1 0.0000 1740 1860 165 165 1740 1860 1905 1855 +4 1 0 99 0 0 14 0.0000 4 105 105 1740 1930 a\001 +-6 +6 2745 1665 3105 2025 +1 3 0 1 0 7 100 0 20 0.000 1 0.0000 2910 1860 165 165 2910 1860 3075 1855 +4 1 0 99 0 0 14 0.0000 4 150 105 2910 1930 b\001 +-6 +6 2745 2115 3105 2475 +1 3 0 1 0 7 100 0 20 0.000 1 0.0000 2910 2310 165 165 2910 2310 3075 2305 +4 1 0 99 0 0 14 0.0000 4 150 105 2910 2380 2\001 +-6 +6 3960 1665 4320 2025 +1 3 0 1 0 7 100 0 20 0.000 1 0.0000 4125 1860 165 165 4125 1860 4290 1855 +4 1 0 99 0 0 14 0.0000 4 105 105 4125 1930 c\001 +-6 +6 3960 2115 4320 2475 +1 3 0 1 0 7 100 0 20 0.000 1 0.0000 4125 2310 165 165 4125 2310 4290 2305 +4 1 0 99 0 0 14 0.0000 4 150 240 4125 2380 -1\001 +-6 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 1351 587 496 902 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 1803 577 2658 892 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2697 1342 1842 1657 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3148 1347 4003 1662 +2 1 0 1 0 7 100 0 -1 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2925 1350 2925 1665 +2 2 2 1 0 7 100 0 -1 3.000 0 0 -1 0 0 5 + 180 900 585 900 585 1755 180 1755 180 900 +2 2 2 1 0 7 100 0 -1 3.000 0 0 -1 0 0 5 + 1530 1665 1935 1665 1935 2520 1530 2520 1530 1665 +2 2 2 1 0 7 100 0 -1 3.000 0 0 -1 0 0 5 + 2700 1665 3105 1665 3105 2520 2700 2520 2700 1665 +2 2 2 1 0 7 100 0 -1 3.000 0 0 -1 0 0 5 + 3915 1665 4320 1665 4320 2520 3915 2520 3915 1665 diff --git a/doc/tutorial.sgml.in b/doc/tutorial.sgml.in new file mode 100644 index 00000000..5d351533 --- /dev/null +++ b/doc/tutorial.sgml.in @@ -0,0 +1,1544 @@ + + + +GiNaC Tutorial + +An open framework for symbolic computation within the C++ programming language + + + + The GiNaC Group + + + ChristianBauer + +
Christian.Bauer@Uni-Mainz.DE
+
+
+ + AlexanderFrink + +
Alexander.Frink@Uni-Mainz.DE
+
+
+ + RichardB.Kreckel + +
Richard.Kreckel@Uni-Mainz.DE
+
+
+ + Others + +
whoever@ThEP.Physik.Uni-Mainz.DE
+
+
+
+
+
+ + +Introduction + +The motivation behind GiNaC derives from the observation that +most present day computer algebra systems (CAS) are linguistically and +semantically impoverished. It is an attempt to overcome the current +situation by extending a well established and standardized computer +language (C++) by some fundamental symbolic capabilities, thus +allowing for integrated systems that embed symbolic manipulations +together with more established areas of computer science (like +computation-intense numeric applications, graphical interfaces, etc.) +under one roof. + +This tutorial is intended for the novice user who is new to GiNaC +but already has some background in C++ programming. However, since a +hand made documentation like this one is difficult to keep in sync +with the development the actual documentation is inside the sources in +the form of comments. That documentation may be parsed by one of the +many Javadoc-like documentation systems. The generated HTML +documenatation is included in the distributed sources (subdir +doc/reference/) or can be accessed directly at URL +http://wwwthep.physik.uni-mainz.de/GiNaC/reference/. +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. + + +License + +The GiNaC framework for symbolic computation within the C++ +programming language is Copyright (C) 1999 Johannes Gutenberg +Universität 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; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. + + + + +A Tour of GiNaC + +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. + +How to use it from within C++ 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: + +My first GiNaC program (a bivariate polynomial) + +#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; +} + +Assuming the file is called hello.cc, on +our system we can compile and run it like this: + +sysprompt> c++ hello.cc -o hello -lcln -lginac +sysprompt> ./hello +355687428096000*x*y+20922789888000*y^2+6402373705728000*x^2 + + + + +Next, there is a more meaningful C++ program that calls a +function which generates Hermite polynomials in a specified free +variable. + +My second GiNaC program (Hermite polynomials) + +#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; +} + +When run, this will type out + +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 + + +This method of generating the coefficients is of course far from +optimal for production purposes. + +In order to show some more examples of what GiNaC can do we +will now use ginsh, a simple GiNaC interactive +shell that provides a convenient window into GiNaC's capabilities. + + +What it can do for you + +After invoking ginsh one can test and +experiment with GiNaC's features much like in other Computer Algebra +Systems except that it does not provide programming constructs like +loops or conditionals. For a concise description of the +ginsh syntax we refer to its accompanied +man-page. + +It can manipulate arbitrary precision integers in a very fast +way. Rational numbers are automatically converted to fractions of +coprime integers: + +> x=3^150; +369988485035126972924700782451696644186473100389722973815184405301748249 +> y=3^149; +123329495011708990974900260817232214728824366796574324605061468433916083 +> x/y; +3 +> y/x; +1/3 + + + +All numbers occuring in GiNaC's expressions can be converted +into floating point numbers with the evalf method, +to arbitrary accuracy: + +> evalf(1/7); +0.14285714285714285714 +> Digits=150; +150 +> evalf(1/7); +0.1428571428571428571428571428571428571428571428571428571428571428571428 +5714285714285714285714285714285714285 + + + +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): + +> a=Pi^2+x; +x+Pi^2 +> evalf(a); +x+9.869604401089358619L0 +> x=2; +2 +> evalf(a); +11.869604401089358619L0 + + + +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: + +> cos(42*Pi); +1 +> cos(acos(x)); +x +> acos(cos(x)); +acos(cos(x)) + +(Note that converting the last input to x would +allow one to conclude that 42*Pi is equal to +0.) + +Linear equation systems can be solved along with basic linear +algebra manipulations over symbolic expressions: + +> 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 + + + +Multivariate polynomials and rational functions may be expanded, +collected and normalized (i.e. converted to a ratio of two coprime +polynomials): + +> 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 + + + + +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): + +> 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) + + + + + + + + + +Installation + +GiNaC's installation follows the spirit of most GNU software. It is +easily installed on your system by three steps: configuration, build, +installation. + +Prerequistes + +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 ISO/IEC 14882:1998(E). We used +GCC 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 /bin/sh, +GNU bash 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 +CLN is extensively used and needs to be installed +on your system. Please get it from ftp://ftp.santafe.edu/pub/gnu/ +or from ftp://ftp.ilog.fr/pub/Users/haible/gnu/ +(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. + +Configuration + +To configure GiNaC means to prepare the source distribution for +building. It is done via a shell script called +configure that is shipped with the sources. +(Actually, this script is by itself created with GNU Autoconf from the +files configure.in and +aclocal.m4.) Since a configure script generated by +GNU Autoconf never prompts, all customization must be done either via +command line parameters or environment variables. It accepts a list +of parameters, the complete set of which can be listed by calling it +with the --help option. The most important ones +will be shortly described in what follows: + + + --enable-shared: When given, this option + switches on the build of a shared library, i.e. a + .so-file. A static libarary (i.e. a + .a-file) is still built. For this to succeed, + GNU libtool needs to be installed on your system. Hence, + configure checks if it can find an executable + libtool in the PATH. If it + doesn't this option is ignored and the default restored, which + means that only a static library will be build. + + + --prefix=PREFIX: The + directory where the compiled library and headers are installed. It + defaults to /usr/local which means that the + library is installed in the directory + /usr/local/lib and the header files in + /usr/local/include/GiNaC and the documentation + (like this one) into /usr/local/share/doc/GiNaC. + + + --libdir=LIBDIR: Use + this option in case you want to have the library installed in some + other directory than + PREFIX/lib/. + + + --includedir=INCLUDEDIR: + Use this option in case you want to have the header files + installed in some other directory than + PREFIX/include/GiNaC/. For + instance, if you specify + --includedir=/usr/include you will end up with + the header files sitting in the directory + /usr/include/GiNaC/. Note that the subdirectory + GiNaC 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). + + + --datadir=DATADIR: + This option may be given in case you want to have the documentation + installed in some other directory than + PREFIX/share/doc/GiNaC/. + + + + +In addition, you may specify some environment variables. +CXX holds the path and the name of the C++ compiler +in case you want to override the default in your path. (The +configure script searches your path for +c++, g++, +gcc, CC, cxx +and cc++ in that order.) It may be very useful to +define some compiler flags with the CXXFLAGS +environment variable, like optimization, debugging information and +warning levels. If ommitted, it defaults to -g +-O2. + +The whole process is illustrated in the following two +examples. (Substitute setenv VARIABLE value for +export VARIABLE=value if the Berkeley C shell is +your login shell.) + +Sample sessions of how to call the +configure-script Simple configuration for a site-wide +GiNaC library assuming everything is in default paths: + +sysprompt> export CXXFLAGS="-Wall -O2" +sysprompt> ./configure --enable-shared + +Configuration for a private GiNaC library with several +components sitting in custom places (site-wide GCC +and private CLN): + +sysprompt> export CXX=/usr/local/gnu/bin/c++ +sysprompt> export CPPFLAGS="${CPPFLAGS} -I${HOME}/include" +sysprompt> export CXXFLAGS="${CXXFLAGS} -ggdb -Wall -ansi -pedantic -O2" +sysprompt> export LDFLAGS="${LDFLAGS} -L${HOME}/lib" +sysprompt> ./configure --enable-shared --prefix=${HOME} + + + + + + +Building GiNaC + +After proper configuration you should just build the whole +library by typing make at the command +prompt and go for a cup of coffee. + +Just to make sure GiNaC works properly you may run a simple test +suite by typing make check. This will compile some +sample programs, run them and compare the output to reference output. +Each of the checks should return a message passed +together with the CPU time used for that particular test. If it does +not, something went wrong. This is mostly intended to be a 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 CLN was installed all right this +step is unlikely to return any errors. + + + +Installation + +To install GiNaC on your system, simply type make +install. 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): + + + libginac.a will go into + PREFIX/lib/ (or + LIBDIR) which defaults to + /usr/local/lib/. So will + libginac.so if the the configure script was + given the option --enable-shared. In that + case, the proper symlinks will be established as well (by running + ldconfig). + + + All the header files will be installed into + PREFIX/include/GiNaC/ (or + INCLUDEDIR/GiNaC/, if + specified). + + + All documentation (HTML, Postscript and DVI) will be stuffed + into + PREFIX/share/doc/GiNaC/ + (or DATADIR/doc/GiNaC/, if + specified). + + + + +Just for the record we will list some other useful make targets: +make clean deletes all files generated by +make, i.e. all the object files. In addition +make distclean removes all files generated by +configuration. And finally make uninstall removes +the installed library and header files. + + Uninstallation does not work + after you have called make distclean since the + Makefile is itself generated by the configuration + from Makefile.in and hence deleted by + make distclean. There are two obvious ways out + of this dilemma. First, you can run the configuration again with + the same PREFIX thus creating a + Makefile with a working + uninstall target. Second, you can do it by hand + since you now know where all the files went during + installation. + + + + + + + +Basic Concepts + +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. + +Expressions + +The most common class of objects a user deals with is the +expression ex, representing a mathematical object +like a variable, number, function, sum, product, etc... Expressions +may be put together to form new expressions, passed as arguments to +functions, and so on. Here is a little collection of valid +expressions: +Examples of expressions + + 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 + + +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. + +Digression: Expressions are reference counted + +An expression is extremely light-weight since internally it +works like a handle to the actual representation and really holds +nothing more than a pointer to some other object. What this means in +practice is that whenever you create two ex and set +the second equal to the first no copying process is involved. Instead, +the copying takes place as soon as you try to change the second. +Consider the simple sequence of code: +Simple copy-on-write semantics + +#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 + // ... +} + + +The line e2 = e1; creates a second expression +pointing to the object held already by e1. The +time involved for this operation is therefore constant, no matter how +large e1 was. Actual copying, however, must take +place in the line e2 += 1 because +e1 and e2 are not handles for +the same object any more. This concept is called +copy-on-write semantics. It increases +performance considerably whenever one object occurs multiple times and +represents a simple garbage collection scheme because when an +ex runs out of scope its destructor checks whether +other expressions handle the object it points to too and deletes the +object from memory if that turns out not to be the case. A slightly +less trivial example of differentiation using the chain-rule should +make clear how powerful this can be. Advanced +copy-on-write semantics + +#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) + // ... +} + + +Here, e1 will actually be referenced three times +while e2 will be referenced two times. When the +power of an expression is built, that expression needs not be +copied. Likewise, since the derivative of a power of an expression can +be easily expressed in terms of that expression, no copying of +e1 is involved when e3 is +constructed. So, when e3 is constructed it will +print as 3*(x+3*y)^2*cos((x+3*y)^3) but the +argument of cos() only holds a reference to +e2 and the factor in front is just +3*e1^2. + + +As a user of GiNaC, you cannot see this mechanism of +copy-on-write semantics. When you insert an expression into a +second expression, the result behaves exactly as if the contents of +the first expression were inserted. But it may be useful to remember +that this is not what happens. Knowing this will enable you to write +much more efficient code. + +So much for expressions. But what exactly are these expressions +handles of? This will be answered in the following sections. + + + +The Class Hierarchy + +GiNaC's class hierarchy consists of several classes representing +mathematical objects, all of which (except for ex +and some helpers) are internally derived from one abstract base class +called basic. You do not have to deal with objects +of class basic, instead you'll be dealing with +symbols and functions of symbols. You'll soon learn in this chapter +how many of the functions on symbols are really classes. This is +because simple symbolic arithmetic is not supported by languages like +C++ so in a certain way GiNaC has to implement its own arithmetic. + +To give an idea about what kinds of symbolic composits may be +built we have a look at the most important classes in the class +hierarchy. The dashed line symbolizes a "points to" or "handles" +relationship while the solid lines stand for "inherits from" +relationships. +
+The GiNaC class hierarchy + +
+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 expairseq, which is a container +for a sequence of pairs each consisting of one expression and a number +(numeric). What is visible to +the user are the derived classes add and +mul, representing sums of terms and products, +respectively. We'll come back later to some more details about these +two classes and motivate the use of pairs in sums and products here.
+ +Digression: Internal representation of products and sums + +Although it should be completely transparent for the user of +GiNaC a short discussion of this topic helps understanding the sources +and also explains performance to a large degree. Consider the +symbolic expression (a+2*b-c)*d, 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: +
+Naive internal representation of <emphasis>d(a+2*b-c)</emphasis> + +
+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. +
+Better internal representation of <emphasis>d(a+2*b-c)</emphasis> + +
+The number 1 under the symbol d +is a hint that multiplication objects can be treated similarly where +the coeffiecients are interpreted as exponents +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 +add and mul are derived from the +same abstract class: the representation is the same, only the +interpretation differs.
+ +
+ +Symbols + +Symbols are for symbolic manipulation what atoms are for +chemistry. You can declare objects of type symbol as any other object +simply by saying symbol x,y;. There is, however, a +catch in here having to do with the fact that C++ is a compiled +language. The information about the symbol's name is thrown away by +the compiler but at a later stage you may want to print expressions +holding your symbols. In order to avoid confusion GiNaC's symbols are +able to know their own name. This is accompilshed by declaring its +name for output at construction time in the fashion symbol +x("x");. + +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 .subs() +method. + + + +Numbers + +For storing numerical things, GiNaC uses Bruno Haible's library +CLN. The classes therein serve as foundation +classes for GiNaC. CLN stands for Class Library +for Numbers or alternatively for Common Lisp Numbers. In order to +find out more about CLN's internals the reader is +refered to the documentation of that library. Suffice to say that it +is by itself build on top of another library, the GNU Multiple +Precision library GMP, which is a extremely fast +library for arbitrary long integers and rationals as well as arbitrary +precision floating point numbers. It is very commonly used by several +popular cryptographic applications. CLN extends +GMP by several useful things: First, it introduces +the complex number field over either reals (i.e. floating point +numbers with arbitrary precision) or rationals. Second, it +automatically converts rationals to integers if the denominator is +unity and complex numbers to real numbers if the imaginary part +vanishes and also correctly treats algebraic functions. Third it +provides good implementations of state-of-the-art algorithms for all +trigonometric and hyperbolic functions as well as for calculation of +some useful constants. + +The user can construct an object of class +numeric in several ways. The following example +shows the four most important constructors: construction from +C-integer, construction of fractions from two integers, construction +from C-float and construction from a string. +Sample C++ program + +#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... + // ... +} + + +Note that all those constructors are explicit +which means you are not allowed to write numeric +two=2;. This is because the basic objects to be handled by +GiNaC are the expressions and we want to keep things simple and wish +objects like pow(x,2) to be handled the same way +as pow(x,a), which means that we need to allow a +general expression as base and exponent. Therefore there is an +implicit construction from a 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. + + +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 global variable, called +Digits. (For those readers who know about Maple: +it behaves very much like Maple's Digits). All +objects of class numeric that are constructed from then on will be +stored with a precision matching that number of decimal digits: +Controlling the precision of floating point numbers + +#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; +} + + +The above example prints the following output to screen: + +in 17 digits: +0.333333333333333333 +3.14159265358979324 +in 60 digits: +0.333333333333333333333333333333333333333333333333333333333333333333 +3.14159265358979323846264338327950288419716939937510582097494459231 + + + +Tests on numbers + +Once you have declared some numbers, assigned them to +expressions and done some arithmetic with them it is frequently +desired to retrieve some kind of information from them like asking +whether that number is integer, rational, real or complex. For those +cases GiNaC provides several useful methods. (Internally, they fall +back to invocations of certain CLN functions.) + +As an example, let's construct some rational number, multiply it +with some multiple of its denominator and check what comes out: +Sample test on objects of type numeric + +#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! + // ... +} + + +Note that the variable answer is constructed here +as an integer but in an intermediate step it holds a rational number +represented as integer numerator and denominator. When multiplied by +10, the denominator becomes unity and the result is automatically +converted to a pure integer again. Internally, the underlying +CLN is responsible for this behaviour and we refer +the reader to CLN's documentation. Suffice to say +that the same behaviour applies to complex numbers as well as return +values of certain functions. Complex numbers are automatically +converted to real numbers if the imaginary part becomes zero. The +full set of tests that can be applied is listed in the following +table. + + + + + + + Method + Returns true if... + + + + + .is_zero() + object is equal to zero + + + .is_positive() + object is not complex and greater than 0 + + + .is_integer() + object is a (non-complex) integer + + + .is_pos_integer() + object is an integer and greater than 0 + + + .is_nonneg_integer() + object is an integer and greater equal 0 + + + .is_even() + object is an even integer + + + .is_odd() + object is an odd integer + + + .is_prime() + object is a prime integer (probabilistic primality test) + + + .is_rational() + object is an exact rational number (integers are rational, too, as are complex extensions like 2/3+7/2*I) + + + .is_real() + object is a real integer, rational or float (i.e. is not complex) + + + + + + + + + + + +Constants + +Constants behave pretty much like symbols except that that they return +some specific number when the method .evalf() is called. + + +The predefined known constants are: + + + + + + + + Name + Common Name + Numerical Value (35 digits) + + + + + Pi + Archimedes' constant + 3.14159265358979323846264338327950288 + + Catalan + Catalan's constant + 0.91596559417721901505460351493238411 + + EulerGamma + Euler's (or Euler-Mascheroni) constant + 0.57721566490153286060651209008240243 + + + + + + + + +Fundamental operations: The <literal>power</literal>, <literal>add</literal> and <literal>mul</literal> classes + +Simple polynomial expressions are written down in GiNaC pretty +much like in other CAS. The necessary operators +, +-, * and / +have been overloaded to achieve this goal. When you run the following +program, the constructor for an object of type mul +is automatically called to hold the product of a +and b and then the constructor for an object of +type add is called to hold the sum of that +mul object and the number one: +Construction of <literal>add</literal> and <literal>mul</literal> objects + +#include <GiNaC/ginac.h> + +int main() +{ + symbol a("a"), b("b"); + ex MyTerm = 1+a*b; + // ... +} + + + +For exponentiation, you have already seen the somewhat clumsy +(though C-ish) statement pow(x,2); to represent +x squared. This direct construction is necessary +since we cannot safely overload the constructor ^ +in C++ to construct a power +object. If we did, it would have two counterintuitive effects: + + + Due to C's operator precedence, + 2*x^2 would be parsed as (2*x)^2. + + + Due to the binding of the operator ^, + x^2^3 would result in x^8. + This would be confusing since most (though not all) other CAS + interpret this as x^6. + + +Both effects are contrary to mathematical notation and differ from the +way most other CAS handle exponentiation, therefore overloading +^ is ruled out. (Also note, that the other +frequently used exponentiation operator ** does not +exist at all in C++). + +To be somewhat more precise, objects of the three classes +described here, are all containers for other expressions. An object +of class power is best viewed as a container with +two slots, one for the basis, one for the exponent. All valid GiNaC +expressions can be inserted. However, basic transformations like +simplifying pow(pow(x,2),3) to +x^6 automatically are only performed when +this is mathematically possible. If we replace the outer exponent +three in the example by some symbols a, the +simplification is not safe and will not be performed, since +a might be 1/2 and +x negative. + +Objects of type add and +mul are containers with an arbitrary number of +slots for expressions to be inserted. Again, simple and safe +simplifications are carried out like transforming +3*x+4-x to 2*x+4. + +The general rule is that when you construct such objects, GiNaC +automatically creates them in canonical form, which might differ from +the form you typed in your program. This allows for rapid comparison +of expressions, since after all a-a is simply zero. +Note, that the canonical form is not necessarily lexicographical +ordering or in any way easily guessable. It is only guaranteed that +constructing the same expression twice, either implicitly or +explicitly, results in the same canonical form. + + + +Built-in Functions + +This chapter is not here yet + + + + + +
+ + + +Important Algorithms + +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: +Methods vs. wrapper functions + +#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; + // ... +} + + +The general rule is that wherever methods accept one or more +parameters (arg1, arg2, ...) +the order of arguments the function wrapper accepts is the same but +preceded by the object to act on (object, +arg1, arg2, ...). 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 +A:=x+1; subs(x=2,A); GiNaC would require +A=x+1; subs(A,x==2); (after proper declaration of A +and x). On the other hand, since MapleV returns 3 on +A:=x^2+3; coeff(A,x,0); (GiNaC: +A=pow(x,2)+3; coeff(A,x,0);) it is clear that +MapleV is not trying to be consistent here. Also, users of MuPAD will +in most cases feel more comfortable with GiNaC's convention. All +function wrappers are always implemented as simple inline functions +which just call the corresponding method and are only provided for +users uncomfortable with OO who are dead set to avoid method +invocations. Generally, a chain of function wrappers is much harder +to read than a chain of methods and should therefore be avoided if +possible. On the other hand, not everything in GiNaC is a method on +class ex and sometimes calling a function cannot be +avoided. + + +Polynomial Expansion + +A polynomial in one or more variables has many equivalent +representations. Some useful ones serve a specific purpose. Consider +for example the trivariate polynomial 4*x*y + x*z + 20*y^2 + +21*y*z + 4*z^2. It is equivalent to the factorized +polynomial (x + 5*y + 4*z)*(4*y + z). Other +representations are the recursive ones where one collects for +exponents in one of the three variable. Since the factors are +themselves polynomials in the remaining two variables the procedure +can be repeated. In our expample, two possibilies would be +(4*y + z)*x + 20*y^2 + 21*y*z + 4*z^2 and +20*y^2 + (21*z + 4*x)*y + 4*z^2 + x*z. + + +To bring an expression into expanded form, its method +.expand() may be called. In our example above, +this corresponds to 4*x*y + x*z + 20*y^2 + 21*y*z + +4*z^2. There is no canonical form in GiNaC. Be prepared to +see different orderings of terms in such sums! + + + +Collecting expressions + +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 +collect() accomplishes this task: + + #include <GiNaC/ginac.h> + ex ex::collect + symbol const & s + +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 + + #include <GiNaC/ginac.h> + int ex::degree + symbol const & s + + + int ex::ldegree + symbol const & s + +where degree() returns the highest coefficient and +ldegree() the lowest one. These two methods work +also reliably on non-expanded input polynomials. This is illustrated +in the following example: + +Collecting expressions in multivariate polynomials + +#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; + // ... +} + + +When run, it returns an output in the following fashion: + +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 + +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. + + + +Polynomial Arithmetic + +GCD and LCM + +The functions for polynomial greatest common divisor and least common +multiple have the synopsis: + + #include <GiNaC/normal.h> + ex gcd + const ex *a, const ex *b + + + ex lcm + const ex *a, const ex *b + + +The functions gcd() and lcm() accepts two expressions +a and b as arguments and return +a new expression, their greatest common divisor or least common +multiple, respectively. If the polynomials a and +b are coprime gcd(a,b) returns 1 +and lcm(a,b) returns the product of +a and b. +Polynomal GCD/LCM + +#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 + // ... +} + + + + + + +The <function>normal</function> method + +While in common symbolic code gcd() and +lcm() are not too heavily used, some basic +simplification occurs frequently. Therefore +.normal(), which provides some basic form of +simplification, has become a method of class ex, +just like .expand(). + + + + + +Symbolic Differentiation + + +Simple polynomial differentiation + +#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 + // ... +} + + + + + +Differentiation with nontrivial functions + +#include <GiNaC/ginac.h> + +int main() +{ + // To Be Done... +} + + + + + + +Series Expansion + +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: +Series expansion + +#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; + \\ ... +} + + + + + + + + + + +Extending GiNaC + +Longish chapter follows here. + + + + + +A Comparison with other CAS + +This chapter will give you some information on how GiNaC +compares to other, traditional Computer Algebra Systems, like +Maple, Mathematica or +Reduce, where it has advantages and disadvantages +over these systems. + +Advantages + +GiNaC has several advantages over traditional Computer +Algebra Systems, like + + + + familiar language: all common CAS implement their own + proprietary grammar which you have to learn first (and maybe learn + again when your vendor chooses to "enhance" it). With GiNaC you + can write your program in common C++, which is + standardized. + + + structured data types: you can build up structured data + types using structs or classes + together with STL features instead of using unnamed lists of lists + of lists. + + + 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. + + + + development tools: powerful development tools exist for + C++, like fancy editors (e.g. with automatic + indentation and syntax highlighting), debuggers, visualization + tools, documentation tools... + + + modularization: C++ programs can + easily be split into modules by separating interface and + implementation. + + + price: GiNaC is distributed under the GNU Public License + which means that it is free and available with source code. And + there are excellent C++-compilers for free, too. + + + + 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. + + + seemless integration: it is somewhere between difficult + and impossible to call CAS functions from within a program + written in C++ or any other programming + language and vice versa. With GiNaC, your symbolic routines + are part of your program. You can easily call third party + libraries, e.g. for numerical evaluation or graphical + interaction. All other approaches are much more cumbersome: they + range from simply ignoring the problem + (i.e. Maple) to providing a + method for "embedding" the system + (i.e. Yacas). + + + 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. + + + + +Disadvantages + +Of course it also has some disadvantages + + + + 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 CINT + C++ interpreter. + + + advanced features: GiNaC cannot compete with a program + like Reduce which exists for more than + 30 years now or Maple which grows since + 1981 by the work of dozens of programmers, with respect to + mathematical features. Integration, factorization, non-trivial + simplifications, limits etc. are missing in GiNaC (and are not + planned for the near future). + + + portability: While the GiNaC library itself is designed + to avoid any platform dependent features (it should compile + on any ANSI compliant C++ compiler), the + currently used version of the CLN library (fast large integer and + arbitrary precision arithmetics) can be compiled only on systems + with a recently new C++ compiler from the + GNU Compiler Collection (GCC). GiNaC uses + recent language features like explicit constructors, mutable + members, RTTI, dynamic_casts and STL, so ANSI compliance is meant + literally. Recent GCC versions starting at + 2.95, although itself not yet ANSI compliant, support all needed + features. + + + + + +Why <literal>C++</literal>? + +Why did we choose to implement GiNaC in C++ +instead of Java or any other language? +C++ is not perfect: type checking is not strict +(casting is possible), separation between interface and implementation +is not complete, object oriented design is not enforced. The main +reason is the often scolded feature of operator overloading in +C++. While it may be true that operating on classes +with a + operator is rarely meaningful, it is +perfectly suited for algebraic expressions. Writing 3x+5y as +3*x+5*y instead of +x.times(3).plus(y.times(5)) looks much more +natural. Furthermore, the main developers are more familiar with +C++ than with any other programming +language. + + + + + + + + + + ISO/IEC 14882:1998 + Programming Languages: C++ + + + + + CLN: A Class Library for Numbers + + + BrunoHaible +
haible@ilog.fr
+
+
+
+ + + + The C++ Programming Language + BjarneStroustrup + 3 + 0-201-88954-4 + Addison Wesley + + + + + + Algorithms for Computer Algebra + + KeithO.Geddes + StephenR.Czapor + GeorgeLabahn + + 0-7923-9259-0 + 1992 + + Kluwer Academic Publishers +
Norwell, Massachusetts
+
+
+
+ + + + Computer Algebra + Systems and Algorithms for Algebraic Computation + + J.H.Davenport + Y.Siret + E.Tournier + + 0-12-204230-1 + 1988 + + Academic Press +
London
+
+
+
+ +
+
+ + + +Index + + + CLN + obtaining + + + + gcd + + + + lcm + gcd + + + + +
diff --git a/ginsh/Makefile.in b/ginsh/Makefile.in new file mode 100644 index 00000000..88516ac9 --- /dev/null +++ b/ginsh/Makefile.in @@ -0,0 +1,82 @@ +# This is the prototype Makefile for ginsh. +SHELL = /bin/sh + +# Not every make knows what CXX is, so we inherit it together with some other +# values from configure which checks it anyways: +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CPPFLAGS = @CPPFLAGS@ -I../ -I../include +DEFS = @DEFS@ +LIBS = @LIBS@ @LEXLIB@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +YACC = @YACC@ + +# Here come the usual install directories in GNU-configure fashion: +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +mandir = @mandir@ +man1dir = ${mandir}/man1 + +# This must be empty if configure couldn't find it in ${PATH}: +MAKEDEPEND = @MAKEDEPEND@ + +# Autoconf macro AC_PROC_INSTALL sets these: +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ -s + +OBJECTS=y.tab.o @LEX_OUTPUT_ROOT@.o ../src/*.o + +all: depend ginsh + +ginsh: ${OBJECTS} + ${CXX} ${CXXFLAGS} ${LDFLAGS} ${OBJECTS} ${LIBS} -o ginsh + +# Targets for installation in install directories. +install: ginsh installdirs + ${INSTALL_PROGRAM} ginsh ${bindir}/ginsh + -${INSTALL_DATA} ginsh.1 ${man1dir}/ginsh.1 + +installdirs: + ${SHELL} mkinstalldirs ${bindir} ${man1dir} + +# Targets for cleaning up. (clean deletes files created by built, distclean +# deletes files created by configuration, uninstall removes all files related +# to ginsh from the system.) +clean: + rm -f y.tab.c y.tab.h @LEX_OUTPUT_ROOT@.c + rm -f *.o *.lo core ginsh + +distclean: clean + rm -f config.status config.log config.cache config.h Makefile Makefile.bak + +uninstall: + rm -f ${bindir}/ginsh + rm -f ${man1dir}/ginsh.1 + +# If Todd Brunhoff's makedepend is installed (it may not---it's part of X11); +# then call it; else wait for trouble ahead; fi; # :-) +depend: + @if [ ${MAKEDEPEND} ]; then \ + echo "calling ${MAKEDEPEND}"; \ + ${MAKEDEPEND} -Y. -Y../include *.cpp 2> /dev/null; \ + fi + +# Special dummy targets: +.PHONY: clean distclean depend all install uninstall check doc +.SUFFIXES: .o .c .h .y .l + +# Suffix rules: +.c.o : + ${CXX} ${CPPFLAGS} ${CXXFLAGS} ${DEFS} -c $< + +# Explicit rules: +y.tab.c y.tab.h: ginsh.y + $(YACC) -d ginsh.y + +@LEX_OUTPUT_ROOT@.c: ginsh.l + $(LEX) ginsh.l + +# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/ginsh/ginsh.1 b/ginsh/ginsh.1 new file mode 100644 index 00000000..69c37830 --- /dev/null +++ b/ginsh/ginsh.1 @@ -0,0 +1,408 @@ +.TH ginsh 1 "October, 1999" "GiNaC" +.SH NAME +ginsh \- GiNaC Interactive Shell +.SH SYNPOSIS +.B ginsh +.SH DESCRIPTION +.B ginsh +is an interactive frontend for the GiNaC symbolic computation framework. +It is intended as a tool for testing and experimenting with GiNaC's +features, not as a replacement for traditional interactive computer +algebra systems. Although it can do many things these traditional systems +can do, ginsh provides no programming constructs like loops or conditional +expressions. If you need this functionality you are advised to write +your program in C++, using the "native" GiNaC class framework. +.SH USAGE +.SS INPUT FORMAT +After startup, ginsh displays a prompt ("> ") signifying that it is ready +to accept your input. Acceptable input are numeric or symbolic expressions +consisting of numbers (e.g. +.BR 42 ", " 2/3 " or " 0.17 ), +symbols (e.g. +.BR x " or " result ), +mathematical operators like +.BR + " and " * , +and functions (e.g. +.BR sin " or " normal ). +ginsh will evaluate the expression and print the result to stdout. Every +input expression must be terminated by a semicolon +.RB ( ; ), +and it is possible to enter multiple expressions on one line. Whitespace +(spaces, tabs, newlines) can be applied freely between tokens. To quit ginsh, +enter +.BR quit " or " exit , +or type an EOF (Ctrl-D) at the prompt. +.SS NUMBERS +ginsh accepts numbers in all formats accepted by CLN (the Class Library for +Numbers, that is the foundation of GiNaC's numerics). This includes arbitrary +precision integers and rationals as well as floating point numbers in standard +or scientific notation (e.g. +.BR 1.2E6 ). +The general rule is that if a number contains a decimal point +.RB ( . ), +it is an (inexact) floating point number; otherwise it is an (exact) integer or +rational. +.SS SYMBOLS +Symbols are made up of a string of alphanumeric characters and the underscore +.RB ( _ ), +with the first character being non-numeric. E.g. +.BR a " and " mu_1 +are acceptable symbol names, while +.B 2pi +is not. It is possible to use symbols with the same names as functions (e.g. +.BR sin ); +ginsh is able to distinguish between the two. +.PP +Symbols can be assigned values by entering +.RS +.IB symbol " = " expression ; +.RE +.PP +To unassign the value of an assigned symbol, type +.RS +.BI unassign(' symbol '); +.RE +.PP +Assigned symbols are automatically evaluated (= replaced by their assigned value) +when they are used. To refer to the unevaluated symbol, put single quotes +.RB ( ' ) +around the name, as demonstrated for the "unassign" command above. +.PP +The following symbols are pre-defined constants that cannot be assigned +a value by the user: +.RS +.TP 8m +.B Pi +Archimedes' Constant +.TP +.B Catalan +Catalan's Constant +.TP +.B EulerGamma +Euler-Mascheroni Constant +.TP +.B I +(-1)^1/2 +.TP +.B FAIL +an object of the GiNaC "fail" class +.RE +.PP +There is also the special +.RS +.B Digits +.RE +symbol that controls the numeric precision of calculations with inexact numbers. +Assigning an integer value to digits will change the precision to the given +number of decimal places. +.SS LAST PRINTED EXPRESSIONS +ginsh provides the three special symbols +.RS +", "" and """ +.RE +that refer to the last, second last, and third last printed expression, respectively. +These are handy if you want to use the results of previous computations in a new +expression. +.SS OPERATORS +ginsh provides the following operators, listed in falling order of precedence: +.RS +.TP 8m +.B ! +postfix factorial +.TP +.B ^ +powering +.TP +.B + +unary plus +.TP +.B \- +unary minus +.TP +.B * +multiplication +.TP +.B % +non-commutative multiplication +.TP +.B / +division +.TP +.B + +addition +.TP +.B \- +subtraction +.TP +.B < +less than +.TP +.B > +greater than +.TP +.B <= +less or equal +.TP +.B >= +greater or equal +.TP +.B == +equal +.TP +.B != +not equal +.TP +.B = +symbol assignment +.RE +.PP +All binary operators are left-associative, with the exception of +.BR ^ " and " = +which are right-associative. The result of the assignment operator +.RB ( = ) +is its right-hand side, so it's possible to assign multiple symbols in one +expression (e.g. +.BR "a = b = c = 2;" ). +.SS LISTS +Lists are used by the +.B subs +and +.B lsolve +functions. A list consists of an opening square bracket +.RB ( [ ), +a (possibly empty) comma-separated sequence of expressions, and a closing square +bracket +.RB ( ] ). +.SS MATRICES +A matrix consists of an opening double square bracket +.RB ( [[ ), +a non-empty comma-separated sequence of matrix rows, and a closing double square +bracket +.RB ( ]] ). +Each matrix row consists of an opening double square bracket +.RB ( [[ ), +a non-empty comma-separated sequence of expressions, and a closing double square +bracket +.RB ( ]] ). +If the rows of a matrix are not of the same length, the width of the matrix +becomes that of the longest row and shorter rows are filled up at the end +with elements of value zero. +.SS FUNCTIONS +A function call in ginsh has the form +.RS +.IB name ( arguments ) +.RE +where +.I arguments +is a comma-separated sequence of expressions. ginsh provides a couple of built-in +functions and also "imports" all symbolic functions defined by GiNaC and additional +libraries. There is no way to define your own functions other than linking ginsh +against a library that defines symbolic GiNaC functions. +.PP +ginsh provides Tab-completion on function names: if you type the first part of +a function name, hitting Tab will complete the name if possible. If the part you +typed is not unique, hitting Tab again will display a list of matching functions. +Hitting Tab twice at the prompt will display the list of all available functions. +.PP +A list of the built-in functions follows. They nearly all work as the +respective GiNaC methods of the same name, so I will not describe them in +detail here. Please refer to the GiNaC documentation. +.PP +.RS +.BI beta( expression ", " expression ) +.br +.BI charpoly( matrix ", " symbol ) +.br +.BI coeff( expression ", " symbol ", " number ) +.br +.BI collect( expression ", " symbol ) +.br +.BI content( expression ", " symbol ) +.br +.BI degree( expression ", " symbol ) +.br +.BI denom( expression ) +.br +.BI determinant( matrix ) +.br +.BI diag( expression... ) +.br +.BI diff( expression ", " "symbol [" ", " number] ) +.br +.BI divide( expression ", " expression ) +.br +.BI eval( "expression [" ", " number] ) +.br +.BI evalf( "expression [" ", " number] ) +.br +.BI expand( expression ) +.br +.BI gcd( expression ", " expression ) +.br +.BI has( expression ", " expression ) +.br +.BI inverse( matrix ) +.br +.BI is( relation ) +\- returns "1" if the +.I relation +is true, "0" otherwise (false or undecided) +.br +.BI lcm( expression ", " expression ) +.br +.BI lcoeff( expression ", " symbol ) +.br +.BI ldegree( expression ", " symbol ) +.br +.BI lsolve( list ", " list ) +.br +.BI nops( expression ) +.br +.BI normal( "expression [" ", " number] ) +.br +.BI numer( expression ) +.br +.BI op( expression ", " number ) +.br +.BI power( expression ", " expression ) +.br +.BI prem( expression ", " expression ", " symbol ) +.br +.BI primpart( expression ", " symbol ) +.br +.BI quo( expression ", " expression ", " symbol ) +.br +.BI rem( expression ", " expression ", " symbol ) +.br +.BI series( expression ", " "symbol [" ", " "number [" ", " number]] ) +.br +.BI sqrfree( expression ", " symbol ) +.br +.BI sqrt( expression ) +.br +.BI subs( expression ", " relation-or-list ) +.br +.BI subs( expression ", " list ", " list ) +.br +.BI tcoeff( expression ", " symbol ) +.br +.BI time( expression ) +\- returns the time in seconds needed to evaluate the given +.I expression +.br +.BI trace( matrix ) +.br +.BI transpose( matrix ) +.br +.BI unassign( symbol ) +.br +.BI unit( expression ", " symbol ) +.RE +.SS SPECIAL COMMANDS +To exit ginsh, enter +.RS +.B quit +.RE +or +.RS +.B exit +.RE +.PP +The command +.RS +.BI print( expression ); +.RE +will print a dump of GiNaC's internal representation for the given +.IR expression . +This is useful for debugging and for learning about GiNaC internals. +.PP +Finally, the shell escape +.RS +.B ! +.RI [ "command " [ arguments ]] +.RE +passes the given +.I command +and optionally +.I arguments +to the shell for execution. With this method, you can execute shell commands +from within ginsh without having to quit. +.SH EXAMPLES +.nf +> a = x^2\-x\-2; +\-x+x^2\-2 +> b = (x+1)^2; +(x+1)^2 +> s = a/b; +(x+1)^(\-2)*(\-x+x^2\-2) +> diff(s, x); +(2*x\-1)*(x+1)^(\-2)\-2*(x+1)^(\-3)*(\-x+x^2\-2) +> normal(s); +(x\-2)*(x+1)^(\-1) +> x = 3^50; +717897987691852588770249 +> s; +717897987691852588770247/717897987691852588770250 +> Digits = 40; +40 +> evalf(s); +0.999999999999999999999995821133292704384960990679L0 +> unassign('x'); +x +> s; +(x+1)^(\-2)*(\-x+x^2\-2) +> lsolve([3*x+5*y == 7], [x, y]); +[x==\-5/3*y+7/3,y==y] +> lsolve([3*x+5*y == 7, \-2*x+10*y == \-5], [x, y]); +[x==19/8,y==\-1/40] +> M = [[ [[a, b]], [[c, d]] ]]; +[[ [[\-x+x^2\-2,(x+1)^2]], [[c,d]] ]] +> determinant(M); +\-2*d\-2*x*c\-x^2*c\-x*d+x^2*d\-c +> collect(", x); +(\-d\-2*c)*x+(d\-c)*x^2\-2*d\-c +> quit +.fi +.SH DIAGNOSTICS +.TP +.RI "parse error at " foo +You entered something which ginsh was unable to parse. Please check the syntax +of your input and try again. +.TP +.RI "argument " num " to " function " must be a " type +The argument number +.I num +to the given +.I function +must be of a certain type (e.g. a symbol, or a list). The first argument has +number 0, the second argument number 1, etc. +.SH AUTHOR +.TP +The GiNaC Group: +.br +Christian Bauer +.br +Alexander Frink +.br +Richard B. Kreckel +.SH SEE ALSO +GiNaC Tutorial \- An open framework for symbolic computation within the +C++ programming language +.PP +CLN \- A Class Library for Numbers, Bruno Haible +.SH COPYRIGHT +Copyright \(co 1999 Johannes Gutenberg Universit\(:at Mainz, Germany + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. diff --git a/ginsh/ginsh.h b/ginsh/ginsh.h new file mode 100644 index 00000000..24f37c00 --- /dev/null +++ b/ginsh/ginsh.h @@ -0,0 +1,34 @@ +/* + * ginsh.h - GiNaC Interactive Shell, global definitions + */ + +#ifndef GINSH_H_ +#define GINSH_H_ + +// yacc semantic type +#define YYSTYPE ex + +// lex functions/variables +extern int yyerror(char *s); +extern int yylex(void); +#if YYTEXT_POINTER +extern char *yytext; +#else +extern char yytext[]; +#endif + +// Table of all used symbols +typedef map sym_tab; +extern sym_tab syms; + +// Ersatz functions +#ifndef HAVE_STRDUP +char *strdup(const char *s) +{ + char *n = (char *)malloc(strlen(s) + 1); + strcpy(n, s); + return n; +} +#endif + +#endif diff --git a/ginsh/ginsh.l b/ginsh/ginsh.l new file mode 100644 index 00000000..f46f9490 --- /dev/null +++ b/ginsh/ginsh.l @@ -0,0 +1,159 @@ +/* + * ginsh.l - GiNaC Interactive Shell, lexical analyzer definition + * + * This file must be processed with flex + */ + + +/* + * Definitions + */ + +%{ +#include "config.h" + +#if STDC_HEADERS +#include +#endif + +extern "C" { +#include +#include +} +#include + +#include + +#include "ginsh.h" +#include "y.tab.h" + +#define YY_INPUT(buf, result, max_size) (result = ginsh_input(buf, max_size)) + +// Table of all used symbols +sym_tab syms; + +// lex input function +static int ginsh_input(char *buf, int max_size); +%} + + /* Abbreviations */ +D [0-9] +E [elEL][-+]?{D}+ +A [a-zA-Z_] +AN [0-9a-zA-Z_] + + +/* + * Lexical rules + */ + +%% +[ \t\n]+ /* skip whitespace */ +\\$ /* skip line continuations */ +"#".* /* skip comments starting with "#" */ +^"!".* system(yytext + 1); /* execute shell command */ + + /* special values */ +Pi yylval = Pi; return T_LITERAL; +EulerGamma yylval = EulerGamma; return T_LITERAL; +Catalan yylval = Catalan; return T_LITERAL; +FAIL yylval = *new fail(); return T_LITERAL; +I yylval = I; return T_NUMBER; +Digits yylval = (long)Digits; return T_DIGITS; + + /* keywords */ +quit|exit return T_QUIT; +print return T_PRINT; +time return T_TIME; +xyzzy return T_XYZZY; +inventory return T_INVENTORY; +look return T_LOOK; +score return T_SCORE; + + /* comparison */ +"==" return T_EQUAL; +"!=" return T_NOTEQ; +"<=" return T_LESSEQ; +">=" return T_GREATEREQ; + + /* last 1..3 expressions */ +\" return T_QUOTE; +\"\" return T_QUOTE2; +\"\"\" return T_QUOTE3; + + /* matrix delimiters */ +\[\[ return T_MATRIX_BEGIN; +\]\] return T_MATRIX_END; + + /* numbers */ +{D}+ | +{D}+"."{D}*({E})? | +{D}*"."{D}+({E})? | +{D}+{E} yylval = numeric(yytext); return T_NUMBER; + + /* symbols */ +{A}{AN}* { + if (syms.find(yytext) == syms.end()) + syms[yytext] = *(new symbol(yytext)); + yylval = syms[yytext]; + return T_SYMBOL; + } + + /* everything else */ +. return *yytext; + +%% + + +/* + * Routines + */ + +static int line_length = 0; +static char *line_read = NULL; +static char *line_ptr; + +// Input function that uses libreadline for interactive input +static int ginsh_input(char *buf, int max_size) +{ + int result; + if (yy_current_buffer->yy_is_interactive) { + int actual; + + // Do we need to read a new line? + if (line_length == 0) { + + // Free old line + if (line_read) + free(line_read); + + // Read new line, prompt "> " + line_read = line_ptr = readline("> "); + + // EOF? + if (!line_read) { + line_length = 0; + return YY_NULL; + } + + // Add non-empty lines to history + line_length = strlen(line_read) + 1; + if (line_length > 1) + add_history(line_read); + + // Reappend trailing '\n' which is stripped by readline() + line_read[line_length - 1] = '\n'; + } + + // Copy data to lex buffer + actual = line_length > max_size ? max_size : line_length; + memcpy(buf, line_ptr, actual); + line_length -= actual; + line_ptr += actual; + result = actual; + + } else if (((result = fread(buf, 1, max_size, yyin)) == 0) && ferror(yyin)) + YY_FATAL_ERROR("input in flex scanner failed"); + + return result; +} diff --git a/ginsh/ginsh.y b/ginsh/ginsh.y new file mode 100644 index 00000000..143eae56 --- /dev/null +++ b/ginsh/ginsh.y @@ -0,0 +1,659 @@ +/* + * ginsh.y - GiNaC Interactive Shell, input grammar definition + * + * This file must be processed with yacc/bison + */ + + +/* + * Definitions + */ + +%{ +#include "config.h" + +#include + +#if HAVE_UNISTD_H +#include +#include +#endif + +#if STDC_HEADERS +#include +#include +#include +#endif + +extern "C" { +#include +#include +} +#include +#include +#include + +#include + +#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 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(*($3.bp)), i->second.serial); + } else { + $$ = (i->second.p)(static_cast(*($3.bp))); + } + } + | T_DIGITS '=' T_NUMBER + {$$ = $3; Digits = ex_to_numeric($3).to_int();} + | T_SYMBOL '=' exp + {$$ = $3; const_cast(&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(*($1.bp))); $$ = es.append($3);} + ; + +list_or_empty: /* empty */ {$$ = *new lst;} + | list {$$ = $1;} + ; + +list : exp {$$ = lst($1);} + | list ',' exp {lst l(static_cast(*($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(*($1.bp))); $$ = l.append($4);} + ; + +row : exp {$$ = lst($1);} + | row ',' exp {lst l(static_cast(*($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= 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(&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::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 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 cols) + cols = l.op(i).nops(); + + // Allocate and fill matrix + matrix &m = *new matrix(rows, cols); + for (i=0; i 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; +}