From f4ea690a3f118bf364190f0ef3c3f6d2ccdf6206 Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Tue, 29 Feb 2000 17:28:13 +0000 Subject: [PATCH] - Completely restructured the checks in subdir check/. - Optimized Laplace expansion of determinants to not compute anything more than once. - Moved int permutation_sign(vector s) from matrix.cpp to utils.h. - A handful of other fixes assiciated with the above. --- INSTALL | 4 +- Makefile.in | 1 + NEWS | 8 + check/Makefile.am | 25 +- check/Makefile.in | 70 ++- ...{inifcns_consist.cpp => check_inifcns.cpp} | 38 +- check/check_lsolve.cpp | 128 ++++ check/check_matrices.cpp | 70 +++ check/check_numeric.cpp | 120 ++++ check/checks.cpp | 79 +++ check/{check.h => checks.h} | 48 +- check/checks.ref | 8 + ...entiation.cpp => exam_differentiation.cpp} | 42 +- check/{linear_solve.cpp => exam_lsolve.cpp} | 43 +- .../{matrix_checks.cpp => exam_matrices.cpp} | 46 +- check/{expand_subs.cpp => exam_misc.cpp} | 73 +-- ...lortensor_check.cpp => exam_noncommut.cpp} | 23 +- ...rmalization.cpp => exam_normalization.cpp} | 92 +-- .../{numeric_consist.cpp => exam_numeric.cpp} | 60 +- .../{paranoia_check.cpp => exam_paranoia.cpp} | 70 +-- check/{poly_gcd.cpp => exam_polygcd.cpp} | 47 +- check/{powerlaws.cpp => exam_powerlaws.cpp} | 35 +- ...{series_expansion.cpp => exam_pseries.cpp} | 38 +- check/exams.cpp | 121 ++++ check/exams.h | 45 ++ check/exams.ref | 22 + check/genex.cpp | 58 ++ check/numeric_output.cpp | 61 -- check/result.ref | 30 - check/run_checks | 7 +- check/run_exams | 4 + check/run_times | 4 + check/time_dennyfliegner.cpp | 96 +++ check/time_gammaseries.cpp | 86 +++ check/{fcntimer.cpp => timer.cpp} | 50 +- check/{main.cpp => times.cpp} | 41 +- check/times.h | 53 ++ check/times.ref | 4 + cint/Makefile.in | 1 + config.h.in | 3 + doc/Makefile.in | 1 + doc/reference/Makefile.in | 1 + doc/tutorial/Makefile.in | 1 + ginac/Makefile.in | 1 + ginac/inifcns.cpp | 14 +- ginac/matrix.cpp | 567 ++++++++++-------- ginac/matrix.h | 16 +- ginac/remember.h | 7 +- ginac/utils.h | 20 + ginsh/Makefile.in | 1 + tools/Makefile.in | 1 + 51 files changed, 1705 insertions(+), 779 deletions(-) rename check/{inifcns_consist.cpp => check_inifcns.cpp} (93%) create mode 100644 check/check_lsolve.cpp create mode 100644 check/check_matrices.cpp create mode 100644 check/check_numeric.cpp create mode 100644 check/checks.cpp rename check/{check.h => checks.h} (57%) create mode 100644 check/checks.ref rename check/{differentiation.cpp => exam_differentiation.cpp} (90%) rename check/{linear_solve.cpp => exam_lsolve.cpp} (81%) rename check/{matrix_checks.cpp => exam_matrices.cpp} (86%) rename check/{expand_subs.cpp => exam_misc.cpp} (60%) rename check/{lortensor_check.cpp => exam_noncommut.cpp} (87%) rename check/{normalization.cpp => exam_normalization.cpp} (69%) rename check/{numeric_consist.cpp => exam_numeric.cpp} (87%) rename check/{paranoia_check.cpp => exam_paranoia.cpp} (86%) rename check/{poly_gcd.cpp => exam_polygcd.cpp} (87%) rename check/{powerlaws.cpp => exam_powerlaws.cpp} (93%) rename check/{series_expansion.cpp => exam_pseries.cpp} (90%) create mode 100644 check/exams.cpp create mode 100644 check/exams.h create mode 100644 check/exams.ref create mode 100644 check/genex.cpp delete mode 100644 check/numeric_output.cpp delete mode 100644 check/result.ref create mode 100755 check/run_exams create mode 100755 check/run_times create mode 100644 check/time_dennyfliegner.cpp create mode 100644 check/time_gammaseries.cpp rename check/{fcntimer.cpp => timer.cpp} (63%) rename check/{main.cpp => times.cpp} (56%) create mode 100644 check/times.h create mode 100644 check/times.ref diff --git a/INSTALL b/INSTALL index aee07da7..a7ef9beb 100644 --- a/INSTALL +++ b/INSTALL @@ -108,5 +108,5 @@ Good luck! Known to work with: | Known not to work with: -----------------------+---------------------------- - Cint 5.14.25 | Cint 5.14.24 - Cint 5.14.26 | Cint 5.14.29 + Cint 5.14.31 | Cint before 5.14.29 + diff --git a/Makefile.in b/Makefile.in index 7e2ca91d..1ab83913 100644 --- a/Makefile.in +++ b/Makefile.in @@ -84,6 +84,7 @@ GINSH_LIBS = @GINSH_LIBS@ LATEX = @LATEX@ LEX = @LEX@ LIBGINACCINT = @LIBGINACCINT@ +LIBTERMCAP = @LIBTERMCAP@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LT_AGE = @LT_AGE@ diff --git a/NEWS b/NEWS index fb41acc9..601e5754 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,13 @@ This file records noteworthy changes. +0.5.4 (?? 2000) +* Algorithms in class matrix (determinant and solve) were replaced by + less brain-dead ones and should now have much better performance. +* Checks were reorganized and split up into three parts: + a) exams (small tests with predefined input) + b) checks (lenghty consistency checks) + c) timings (for crude benchmarking) + 0.5.3 (23 February 2000) * A more flexible scheme for registering functions was implemented, allowing for remembering, too. diff --git a/check/Makefile.am b/check/Makefile.am index 87976d8f..96ec4089 100644 --- a/check/Makefile.am +++ b/check/Makefile.am @@ -1,12 +1,17 @@ ## Process this file with automake to produce Makefile.in -TESTS = run_checks -check_PROGRAMS = check_ginac -check_ginac_SOURCES = paranoia_check.cpp numeric_output.cpp \ - numeric_consist.cpp powerlaws.cpp expand_subs.cpp inifcns_consist.cpp \ - differentiation.cpp poly_gcd.cpp normalization.cpp matrix_checks.cpp \ - linear_solve.cpp series_expansion.cpp lortensor_check.cpp \ - fcntimer.cpp main.cpp check.h -check_ginac_LDADD = ../ginac/libginac.la +TESTS = run_exams run_checks run_times +check_PROGRAMS = exams checks times +exams_SOURCES = exam_paranoia.cpp exam_numeric.cpp exam_powerlaws.cpp \ + exam_differentiation.cpp exam_polygcd.cpp exam_normalization.cpp \ + exam_pseries.cpp exam_matrices.cpp exam_lsolve.cpp exam_noncommut.cpp \ + exam_misc.cpp exams.cpp exams.h +exams_LDADD = ../ginac/libginac.la +checks_SOURCES = check_numeric.cpp check_inifcns.cpp check_matrices.cpp \ + check_lsolve.cpp genex.cpp checks.cpp checks.h +checks_LDADD = ../ginac/libginac.la +times_SOURCES = time_dennyfliegner.cpp time_gammaseries.cpp timer.cpp \ + times.cpp times.h +times_LDADD = ../ginac/libginac.la INCLUDES = -I$(srcdir)/../ginac -CLEANFILES = result.out -EXTRA_DIST = result.ref run_checks +CLEANFILES = exams.out checks.out times.out +EXTRA_DIST = exams.ref checks.ref times.ref run_exams run_checks run_times diff --git a/check/Makefile.in b/check/Makefile.in index 0a17c446..0410e062 100644 --- a/check/Makefile.in +++ b/check/Makefile.in @@ -84,6 +84,7 @@ GINSH_LIBS = @GINSH_LIBS@ LATEX = @LATEX@ LEX = @LEX@ LIBGINACCINT = @LIBGINACCINT@ +LIBTERMCAP = @LIBTERMCAP@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LT_AGE = @LT_AGE@ @@ -102,14 +103,20 @@ TUTORIAL_TARGETS = @TUTORIAL_TARGETS@ VERSION = @VERSION@ YACC = @YACC@ -TESTS = run_checks -check_PROGRAMS = check_ginac -check_ginac_SOURCES = paranoia_check.cpp numeric_output.cpp numeric_consist.cpp powerlaws.cpp expand_subs.cpp inifcns_consist.cpp differentiation.cpp poly_gcd.cpp normalization.cpp matrix_checks.cpp linear_solve.cpp series_expansion.cpp lortensor_check.cpp fcntimer.cpp main.cpp check.h +TESTS = run_exams run_checks run_times +check_PROGRAMS = exams checks times +exams_SOURCES = exam_paranoia.cpp exam_numeric.cpp exam_powerlaws.cpp exam_differentiation.cpp exam_polygcd.cpp exam_normalization.cpp exam_pseries.cpp exam_matrices.cpp exam_lsolve.cpp exam_noncommut.cpp exam_misc.cpp exams.cpp exams.h -check_ginac_LDADD = ../ginac/libginac.la +exams_LDADD = ../ginac/libginac.la +checks_SOURCES = check_numeric.cpp check_inifcns.cpp check_matrices.cpp check_lsolve.cpp genex.cpp checks.cpp checks.h + +checks_LDADD = ../ginac/libginac.la +times_SOURCES = time_dennyfliegner.cpp time_gammaseries.cpp timer.cpp times.cpp times.h + +times_LDADD = ../ginac/libginac.la INCLUDES = -I$(srcdir)/../ginac -CLEANFILES = result.out -EXTRA_DIST = result.ref run_checks +CLEANFILES = exams.out checks.out times.out +EXTRA_DIST = exams.ref checks.ref times.ref run_exams run_checks run_times mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../config.h CONFIG_CLEAN_FILES = @@ -118,12 +125,19 @@ DEFS = @DEFS@ -I. -I$(srcdir) -I.. CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ -check_ginac_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 matrix_checks.o \ -linear_solve.o series_expansion.o lortensor_check.o fcntimer.o main.o -check_ginac_DEPENDENCIES = ../ginac/libginac.la -check_ginac_LDFLAGS = +exams_OBJECTS = exam_paranoia.o exam_numeric.o exam_powerlaws.o \ +exam_differentiation.o exam_polygcd.o exam_normalization.o \ +exam_pseries.o exam_matrices.o exam_lsolve.o exam_noncommut.o \ +exam_misc.o exams.o +exams_DEPENDENCIES = ../ginac/libginac.la +exams_LDFLAGS = +checks_OBJECTS = check_numeric.o check_inifcns.o check_matrices.o \ +check_lsolve.o genex.o checks.o +checks_DEPENDENCIES = ../ginac/libginac.la +checks_LDFLAGS = +times_OBJECTS = time_dennyfliegner.o time_gammaseries.o timer.o times.o +times_DEPENDENCIES = ../ginac/libginac.la +times_LDFLAGS = CXXFLAGS = @CXXFLAGS@ CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) @@ -141,14 +155,16 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP_ENV = --best -DEP_FILES = .deps/differentiation.P .deps/expand_subs.P \ -.deps/fcntimer.P .deps/inifcns_consist.P .deps/linear_solve.P \ -.deps/lortensor_check.P .deps/main.P .deps/matrix_checks.P \ -.deps/normalization.P .deps/numeric_consist.P .deps/numeric_output.P \ -.deps/paranoia_check.P .deps/poly_gcd.P .deps/powerlaws.P \ -.deps/series_expansion.P -SOURCES = $(check_ginac_SOURCES) -OBJECTS = $(check_ginac_OBJECTS) +DEP_FILES = .deps/check_inifcns.P .deps/check_lsolve.P \ +.deps/check_matrices.P .deps/check_numeric.P .deps/checks.P \ +.deps/exam_differentiation.P .deps/exam_lsolve.P .deps/exam_matrices.P \ +.deps/exam_misc.P .deps/exam_noncommut.P .deps/exam_normalization.P \ +.deps/exam_numeric.P .deps/exam_paranoia.P .deps/exam_polygcd.P \ +.deps/exam_powerlaws.P .deps/exam_pseries.P .deps/exams.P .deps/genex.P \ +.deps/time_dennyfliegner.P .deps/time_gammaseries.P .deps/timer.P \ +.deps/times.P +SOURCES = $(exams_SOURCES) $(checks_SOURCES) $(times_SOURCES) +OBJECTS = $(exams_OBJECTS) $(checks_OBJECTS) $(times_OBJECTS) all: all-redirect .SUFFIXES: @@ -202,9 +218,17 @@ distclean-libtool: maintainer-clean-libtool: -check_ginac: $(check_ginac_OBJECTS) $(check_ginac_DEPENDENCIES) - @rm -f check_ginac - $(CXXLINK) $(check_ginac_LDFLAGS) $(check_ginac_OBJECTS) $(check_ginac_LDADD) $(LIBS) +exams: $(exams_OBJECTS) $(exams_DEPENDENCIES) + @rm -f exams + $(CXXLINK) $(exams_LDFLAGS) $(exams_OBJECTS) $(exams_LDADD) $(LIBS) + +checks: $(checks_OBJECTS) $(checks_DEPENDENCIES) + @rm -f checks + $(CXXLINK) $(checks_LDFLAGS) $(checks_OBJECTS) $(checks_LDADD) $(LIBS) + +times: $(times_OBJECTS) $(times_DEPENDENCIES) + @rm -f times + $(CXXLINK) $(times_LDFLAGS) $(times_OBJECTS) $(times_LDADD) $(LIBS) .cpp.o: $(CXXCOMPILE) -c $< .cpp.lo: diff --git a/check/inifcns_consist.cpp b/check/check_inifcns.cpp similarity index 93% rename from check/inifcns_consist.cpp rename to check/check_inifcns.cpp index c30ddefe..fb7d9993 100644 --- a/check/inifcns_consist.cpp +++ b/check/check_inifcns.cpp @@ -1,4 +1,4 @@ -/** @file inifcns_consist.cpp +/** @file check_inifcns.cpp * * This test routine applies assorted tests on initially known higher level * functions. */ @@ -21,17 +21,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "ginac.h" - -#ifndef NO_NAMESPACE_GINAC -using namespace GiNaC; -#endif // ndef NO_NAMESPACE_GINAC +#include "checks.h" /* Some tests on the sine trigonometric function. */ static unsigned inifcns_consist_sin(void) { unsigned result = 0; - bool errorflag; + bool errorflag = false; // sin(n*Pi) == 0? errorflag = false; @@ -68,7 +64,7 @@ static unsigned inifcns_consist_sin(void) errorflag = false; ex argument; numeric epsilon(double(1e-8)); - for (int n=-240; n<=240; ++n) { + for (int n=-340; n<=340; ++n) { argument = n*Pi/60; if (abs(sin(evalf(argument))-evalf(sin(argument)))>epsilon) { clog << "sin(" << argument << ") returns " @@ -123,7 +119,7 @@ static unsigned inifcns_consist_cos(void) errorflag = false; ex argument; numeric epsilon(double(1e-8)); - for (int n=-240; n<=240; ++n) { + for (int n=-340; n<=340; ++n) { argument = n*Pi/60; if (abs(cos(evalf(argument))-evalf(cos(argument)))>epsilon) { clog << "cos(" << argument << ") returns " @@ -151,7 +147,7 @@ static unsigned inifcns_consist_tan(void) errorflag = false; ex argument; numeric epsilon(double(1e-8)); - for (int n=-240; n<=240; ++n) { + for (int n=-340; n<=340; ++n) { if (!(n%30) && (n%60)) // skip poles ++n; argument = n*Pi/60; @@ -332,26 +328,26 @@ static unsigned inifcns_consist_zeta(void) return result; } -unsigned inifcns_consist(void) +unsigned check_inifcns(void) { unsigned result = 0; - cout << "checking consistency of symbolic functions..." << flush; + cout << "checking consistency of symbolic functions" << flush; clog << "---------consistency of symbolic functions:" << endl; - result += inifcns_consist_sin(); - result += inifcns_consist_cos(); - result += inifcns_consist_tan(); - result += inifcns_consist_trans(); - result += inifcns_consist_gamma(); - result += inifcns_consist_psi(); - result += inifcns_consist_zeta(); + result += inifcns_consist_sin(); cout << '.' << flush; + result += inifcns_consist_cos(); cout << '.' << flush; + result += inifcns_consist_tan(); cout << '.' << flush; + result += inifcns_consist_trans(); cout << '.' << flush; + result += inifcns_consist_gamma(); cout << '.' << flush; + result += inifcns_consist_psi(); cout << '.' << flush; + result += inifcns_consist_zeta(); cout << '.' << flush; if (!result) { - cout << " passed "; + cout << " passed " << endl; clog << "(no output)" << endl; } else { - cout << " failed "; + cout << " failed " << endl; } return result; diff --git a/check/check_lsolve.cpp b/check/check_lsolve.cpp new file mode 100644 index 00000000..4d1f2373 --- /dev/null +++ b/check/check_lsolve.cpp @@ -0,0 +1,128 @@ +/** @file check_lsolve.cpp + * + * These test routines do some simple checks on solving linear systems of + * symbolic equations. */ + +/* + * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "checks.h" + +static unsigned lsolve1(int size) +{ + // A dense size x size matrix in dense univariate random polynomials + // of order 4. + unsigned result = 0; + symbol a("a"); + ex sol; + + // Create two dense linear matrices A and B where all entries are random + // univariate polynomials + matrix A(size,size), B(size,2), X(size,2); + for (int ro=0; ro1.0001 && ratio<0.9999) { + clog << "(" << num << "/" << den << ")^(" << nm + << ") erroneously evaluated to " << radical; + errorflag = true; + } + } + } + if (errorflag) + ++result; + + return result; +} + +unsigned check_numeric(void) +{ + unsigned result = 0; + + cout << "checking consistency of numeric types" << flush; + clog << "---------consistency of numeric types:" << endl; + + result += check_numeric1(); cout << '.' << flush; + result += check_numeric2(); cout << '.' << flush; + + if (!result) { + cout << " passed " << endl; + clog << "(no output)" << endl; + } else { + cout << " failed " << endl; + } + + return result; +} diff --git a/check/checks.cpp b/check/checks.cpp new file mode 100644 index 00000000..7a979f08 --- /dev/null +++ b/check/checks.cpp @@ -0,0 +1,79 @@ +/** @file checks.cpp + * + * Main program that calls the individual tests. */ + +/* + * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include "checks.h" + +int main() +{ + unsigned result = 0; + + srand((unsigned)time(NULL)); + + try { + for (int i=0; i<1; ++i) + result += check_numeric(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + try { + for (int i=0; i<1; ++i) + result += check_inifcns(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + try { + for (int i=0; i<1; ++i) + result += check_matrices(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + try { + for (int i=0; i<1; ++i) + result += check_lsolve(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + if (result) { + cout << "Error: something went wrong. "; + if (result == 1) { + cout << "(one failure)" << endl; + } else { + cout << "(" << result << " individual failures)" << endl; + } + cout << "please check check.out against check.ref for more details." + << endl << "happy debugging!" << endl; + } + + return result; +} diff --git a/check/check.h b/check/checks.h similarity index 57% rename from check/check.h rename to check/checks.h index 7bdfe2c9..02fb4eb8 100644 --- a/check/check.h +++ b/check/checks.h @@ -1,4 +1,4 @@ -/** @file check.h +/** @file checks.h * * Prototypes for all individual checks. */ @@ -20,26 +20,26 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#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 linear_solve(); -unsigned series_expansion(); -unsigned lortensor_check(); - -#endif // ndef CHECK_H +#ifndef CHECKS_H +#define CHECKS_H + +// For rand() and friends: +#include + +#include "ginac.h" + +#ifndef NO_NAMESPACE_GINAC +using namespace GiNaC; +#endif // ndef NO_NAMESPACE_GINAC + +// prototypes for the expression generating functions in: +const ex dense_univariate_poly(const symbol & x, unsigned degree); +const ex dense_bivariate_poly(const symbol & x1, const symbol & x2, unsigned degree); + +// prototypes for all individual checks should be unsigned fcn(): +unsigned check_numeric(); +unsigned check_inifcns(); +unsigned check_matrices(); +unsigned check_lsolve(); + +#endif // ndef CHECKS_H diff --git a/check/checks.ref b/check/checks.ref new file mode 100644 index 00000000..a109f51b --- /dev/null +++ b/check/checks.ref @@ -0,0 +1,8 @@ +---------consistency of numeric types: +(no output) +---------consistency of symbolic functions: +(no output) +---------symbolic matrix manipulations: +(no output) +---------linear solve: +(no output) diff --git a/check/differentiation.cpp b/check/exam_differentiation.cpp similarity index 90% rename from check/differentiation.cpp rename to check/exam_differentiation.cpp index 307bd59a..0b1e7f19 100644 --- a/check/differentiation.cpp +++ b/check/exam_differentiation.cpp @@ -1,4 +1,4 @@ -/** @file differentiation.cpp +/** @file exam_differentiation.cpp * * Tests for symbolic differentiation, including various functions. */ @@ -20,11 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "ginac.h" - -#ifndef NO_NAMESPACE_GINAC -using namespace GiNaC; -#endif // ndef NO_NAMESPACE_GINAC +#include "exams.h" static unsigned check_diff(const ex &e, const symbol &x, const ex &d, unsigned nth=1) @@ -59,7 +55,7 @@ static unsigned check_diff(const ex &e, const symbol &x, } // Simple (expanded) polynomials -static unsigned differentiation1(void) +static unsigned exam_differentiation1(void) { unsigned result = 0; symbol x("x"), y("y"); @@ -111,7 +107,7 @@ static unsigned differentiation1(void) } // Trigonometric functions -static unsigned differentiation2(void) +static unsigned exam_differentiation2(void) { unsigned result = 0; symbol x("x"), y("y"), a("a"), b("b"); @@ -160,7 +156,7 @@ static unsigned differentiation2(void) } // exp function -static unsigned differentiation3(void) +static unsigned exam_differentiation3(void) { unsigned result = 0; symbol x("x"), y("y"), a("a"), b("b"); @@ -188,7 +184,7 @@ static unsigned differentiation3(void) } // log functions -static unsigned differentiation4(void) +static unsigned exam_differentiation4(void) { unsigned result = 0; symbol x("x"), y("y"), a("a"), b("b"); @@ -218,7 +214,7 @@ static unsigned differentiation4(void) } // Functions with two variables -static unsigned differentiation5(void) +static unsigned exam_differentiation5(void) { unsigned result = 0; symbol x("x"), y("y"), a("a"), b("b"); @@ -253,7 +249,7 @@ static unsigned differentiation5(void) } // Series -static unsigned differentiation6(void) +static unsigned exam_differentiation6(void) { symbol x("x"); ex e, d, ed; @@ -272,25 +268,25 @@ static unsigned differentiation6(void) return 0; } -unsigned differentiation(void) +unsigned exam_differentiation(void) { unsigned result = 0; - cout << "checking symbolic differentiation..." << flush; - clog << "---------symbolic differentiation:" << endl; + cout << "examining symbolic differentiation" << flush; + clog << "----------symbolic differentiation:" << endl; - result += differentiation1(); - result += differentiation2(); - result += differentiation3(); - result += differentiation4(); - result += differentiation5(); - result += differentiation6(); + result += exam_differentiation1(); cout << '.' << flush; + result += exam_differentiation2(); cout << '.' << flush; + result += exam_differentiation3(); cout << '.' << flush; + result += exam_differentiation4(); cout << '.' << flush; + result += exam_differentiation5(); cout << '.' << flush; + result += exam_differentiation6(); cout << '.' << flush; if (!result) { - cout << " passed "; + cout << " passed " << endl; clog << "(no output)" << endl; } else { - cout << " failed "; + cout << " failed " << endl; } return result; } diff --git a/check/linear_solve.cpp b/check/exam_lsolve.cpp similarity index 81% rename from check/linear_solve.cpp rename to check/exam_lsolve.cpp index d006beb9..dfa71da2 100644 --- a/check/linear_solve.cpp +++ b/check/exam_lsolve.cpp @@ -1,7 +1,6 @@ -/** @file linear_solve.cpp +/** @file exam_lsolve.cpp * - * These test routines do some simple checks on solving linear systems of - * symbolic equations. */ + * These exams test solving small linear systems of symbolic equations. */ /* * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany @@ -21,13 +20,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "ginac.h" +#include "exams.h" -#ifndef NO_NAMESPACE_GINAC -using namespace GiNaC; -#endif // ndef NO_NAMESPACE_GINAC - -static unsigned lsolve1(void) +static unsigned exam_lsolve1(void) { // A trivial example. unsigned result = 0; @@ -45,9 +40,9 @@ static unsigned lsolve1(void) return result; } -static unsigned lsolve2a(void) +static unsigned exam_lsolve2a(void) { - // An example from the Maple online-help. + // An example from the Maple online help. unsigned result = 0; symbol a("a"), b("b"), x("x"), y("y"); lst eqns, vars; @@ -73,9 +68,9 @@ static unsigned lsolve2a(void) return result; } -static unsigned lsolve2b(void) +static unsigned exam_lsolve2b(void) { - // A boring example from Mathematica's online-help. + // A boring example from Mathematica's online help. unsigned result = 0; symbol x("x"), y("y"); lst eqns, vars; @@ -101,9 +96,9 @@ static unsigned lsolve2b(void) return result; } -static unsigned lsolve2c(void) +static unsigned exam_lsolve2c(void) { - // An example from the Maple online-help. + // An example from the Maple online help. unsigned result = 0; symbol x("x"), y("y"); lst eqns, vars; @@ -129,23 +124,23 @@ static unsigned lsolve2c(void) return result; } -unsigned linear_solve(void) +unsigned exam_lsolve(void) { unsigned result = 0; - cout << "checking linear solve..." << flush; - clog << "---------linear solve:" << endl; + cout << "examining linear solve" << flush; + clog << "----------linear solve:" << endl; - result += lsolve1(); - result += lsolve2a(); - result += lsolve2b(); - result += lsolve2c(); + result += exam_lsolve1(); cout << '.' << flush; + result += exam_lsolve2a(); cout << '.' << flush; + result += exam_lsolve2b(); cout << '.' << flush; + result += exam_lsolve2c(); cout << '.' << flush; if (!result) { - cout << " passed "; + cout << " passed " << endl; clog << "(no output)" << endl; } else { - cout << " failed "; + cout << " failed " << endl; } return result; diff --git a/check/matrix_checks.cpp b/check/exam_matrices.cpp similarity index 86% rename from check/matrix_checks.cpp rename to check/exam_matrices.cpp index 9e907ec3..81fed94e 100644 --- a/check/matrix_checks.cpp +++ b/check/exam_matrices.cpp @@ -1,6 +1,6 @@ -/** @file matrix_checks.cpp +/** @file exam_matrices.cpp * - * Here we test manipulations on GiNaC's symbolic matrices. */ + * Here we examine manipulations on GiNaC's symbolic matrices. */ /* * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany @@ -21,17 +21,13 @@ */ #include -#include "ginac.h" - -#ifndef NO_NAMESPACE_GINAC -using namespace GiNaC; -#endif // ndef NO_NAMESPACE_GINAC +#include "exams.h" static unsigned matrix_determinants(void) { unsigned result = 0; ex det; - matrix m1(1,1), m2(2,2), m3(3,3); + matrix m1(1,1), m2(2,2), m3(3,3), m4(4,4); symbol a("a"), b("b"), c("c"); symbol d("d"), e("e"), f("f"); symbol g("g"), h("h"), i("i"); @@ -87,6 +83,15 @@ static unsigned matrix_determinants(void) ++result; } + // check sparse symbolic 4x4 matrix determinant + m4.set(0,1,a).set(1,0,b).set(3,2,c).set(2,3,d); + det = m4.determinant(); + if (det != a*b*c*d) { + clog << "determinant of 4x4 matrix " << m4 + << " 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); @@ -204,8 +209,7 @@ static unsigned matrix_misc(void) bool caught=false; try { m5 = inverse(m4); - } - catch (std::runtime_error err) { + } catch (std::runtime_error err) { caught=true; } if (!caught) { @@ -217,24 +221,24 @@ static unsigned matrix_misc(void) return result; } -unsigned matrix_checks(void) +unsigned exam_matrices(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(); + cout << "examining symbolic matrix manipulations" << flush; + clog << "----------symbolic matrix manipulations:" << endl; + + result += matrix_determinants(); cout << '.' << flush; + result += matrix_invert1(); cout << '.' << flush; + result += matrix_invert2(); cout << '.' << flush; + result += matrix_invert3(); cout << '.' << flush; + result += matrix_misc(); cout << '.' << flush; if (!result) { - cout << " passed "; + cout << " passed " << endl; clog << "(no output)" << endl; } else { - cout << " failed "; + cout << " failed " << endl; } return result; diff --git a/check/expand_subs.cpp b/check/exam_misc.cpp similarity index 60% rename from check/expand_subs.cpp rename to check/exam_misc.cpp index 419cea7f..86bd12ab 100644 --- a/check/expand_subs.cpp +++ b/check/exam_misc.cpp @@ -1,17 +1,6 @@ -/** @file expand_subs.cpp +/** @file exam_misc.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). */ - + */ /* * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany * @@ -31,71 +20,73 @@ */ -#include "ginac.h" +#include "exams.h" -#ifndef NO_NAMESPACE_GINAC -using namespace GiNaC; -#endif // ndef NO_NAMESPACE_GINAC - -#define VECSIZE 100 - -static unsigned expand_subs1(void) +#define VECSIZE 30 +static unsigned exam_expand_subs(void) { + unsigned result = 0; symbol a1("a1"); symbol a[VECSIZE]; ex e, aux; - + a[1] = a1; for (unsigned i=0; i -#include "ginac.h" - -#ifndef NO_NAMESPACE_GINAC -using namespace GiNaC; -#endif // ndef NO_NAMESPACE_GINAC +#include "exams.h" static unsigned lortensor_check1(void) { @@ -90,21 +85,21 @@ static unsigned lortensor_check2(void) return result; } -unsigned lortensor_check(void) +unsigned exam_noncommut(void) { unsigned result = 0; - cout << "checking manipulations of lortensor objects..." << flush; - clog << "---------manipulations of lortensor objects:" << endl; + cout << "examining behaviour of noncommutative objects" << flush; + clog << "----------behaviour of noncommutative objects:" << endl; - result += lortensor_check1(); - result += lortensor_check2(); + result += lortensor_check1(); cout << '.' << flush; + result += lortensor_check2(); cout << '.' << flush; if (!result) { - cout << " passed "; + cout << " passed " << endl; clog << "(no output)" << endl; } else { - cout << " failed "; + cout << " failed " << endl; } return result; diff --git a/check/normalization.cpp b/check/exam_normalization.cpp similarity index 69% rename from check/normalization.cpp rename to check/exam_normalization.cpp index 814c45be..98e1d7c5 100644 --- a/check/normalization.cpp +++ b/check/exam_normalization.cpp @@ -1,4 +1,4 @@ -/** @file normalization.cpp +/** @file exam_normalization.cpp * * Rational function normalization test suite. */ @@ -20,11 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "ginac.h" - -#ifndef NO_NAMESPACE_GINAC -using namespace GiNaC; -#endif // ndef NO_NAMESPACE_GINAC +#include "exams.h" static symbol w("w"), x("x"), y("y"), z("z"); @@ -39,7 +35,7 @@ static unsigned check_normal(const ex &e, const ex &d) return 0; } -static unsigned normal1(void) +static unsigned exam_normal1(void) { unsigned result = 0; ex e, d; @@ -62,20 +58,28 @@ static unsigned normal1(void) e = pow(x, -1) + x/(x+1); d = (pow(x, 2)+x+1)/(x*(x+1)); result += check_normal(e, d); - - // Fraction cancellation - e = numeric(1)/2 * z * (2*x + 2*y); - d = z * (x + y); - result += check_normal(e, d); - e = numeric(1)/6 * z * (3*x + 3*y) * (2*x + 2*w); - d = z * (x + y) * (x + w); - result += check_normal(e, d); - - e = (3*x + 3*y) * (w/3 + z/3); - d = (x + y) * (w + z); - result += check_normal(e, d); + return result; +} +static unsigned exam_normal2(void) +{ + unsigned result = 0; + ex e, d; + + // Fraction cancellation + e = numeric(1)/2 * z * (2*x + 2*y); + d = z * (x + y); + result += check_normal(e, d); + + e = numeric(1)/6 * z * (3*x + 3*y) * (2*x + 2*w); + d = z * (x + y) * (x + w); + result += check_normal(e, d); + + e = (3*x + 3*y) * (w/3 + z/3); + d = (x + y) * (w + z); + result += check_normal(e, d); + 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); @@ -83,16 +87,24 @@ static unsigned normal1(void) e = (pow(x, -1) + x) / (pow(x , 2) * 2 + 2); d = pow(x * 2, -1); result += check_normal(e, d); + + // Fraction cancellation with rational coefficients + e = (pow(x, 2) - pow(y, 2)) / pow(x/2 - y/2, 3); + d = (8 * x + 8 * y) / (pow(x, 2) + pow(y, 2) - x * y * 2); + result += check_normal(e, d); + + // Fraction cancellation with rational coefficients + e = z/5 * (x/7 + y/10) / (x/14 + y/20); + d = 2*z/5; + result += check_normal(e, d); + + return result; +} - // Fraction cancellation with rational coefficients - e = (pow(x, 2) - pow(y, 2)) / pow(x/2 - y/2, 3); - d = (8 * x + 8 * y) / (pow(x, 2) + pow(y, 2) - x * y * 2); - result += check_normal(e, d); - - // Fraction cancellation with rational coefficients - e = z/5 * (x/7 + y/10) / (x/14 + y/20); - d = 2*z/5; - result += check_normal(e, d); +static unsigned exam_normal3(void) +{ + unsigned result = 0; + ex e, d; // Distribution of powers e = pow(x/y, 2); @@ -109,6 +121,14 @@ static unsigned normal1(void) d = pow((pow(x, 2) + 1) / x, numeric(1)/2); result += check_normal(e, d); + return result; +} + +static unsigned exam_normal4(void) +{ + unsigned result = 0; + ex 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); @@ -137,20 +157,24 @@ static unsigned normal1(void) return result; } -unsigned normalization(void) +unsigned exam_normalization(void) { unsigned result = 0; - cout << "checking rational function normalization..." << flush; - clog << "---------rational function normalization:" << endl; + cout << "examining rational function normalization" << flush; + clog << "----------rational function normalization:" << endl; - result += normal1(); + result += exam_normal1(); cout << '.' << flush; + result += exam_normal2(); cout << '.' << flush; + result += exam_normal3(); cout << '.' << flush; + result += exam_normal4(); cout << '.' << flush; if (!result) { - cout << " passed "; + cout << " passed " << endl; clog << "(no output)" << endl; } else { - cout << " failed "; + cout << " failed " << endl; } + return result; } diff --git a/check/numeric_consist.cpp b/check/exam_numeric.cpp similarity index 87% rename from check/numeric_consist.cpp rename to check/exam_numeric.cpp index 5839da10..d3c1264a 100644 --- a/check/numeric_consist.cpp +++ b/check/exam_numeric.cpp @@ -1,7 +1,7 @@ -/** @file numeric_consist.cpp +/** @file exam_numeric.cpp * - * This test routine creates some numbers and check the result of several - * boolean tests on these numbers like is_integer() etc... */ + * These exams creates some numbers and check the result of several boolean + * tests on these numbers like is_integer() etc... */ /* * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany @@ -21,16 +21,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include -#include "ginac.h" - -#ifndef NO_NAMESPACE_GINAC -using namespace GiNaC; -#endif // ndef NO_NAMESPACE_GINAC +#include "exams.h" /* Simple and maybe somewhat pointless consistency tests of assorted tests and * conversions. */ -static unsigned numeric_consist1(void) +static unsigned exam_numeric1(void) { unsigned result = 0; numeric test_int1(42); @@ -107,23 +102,6 @@ static unsigned numeric_consist1(void) ++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; } @@ -132,7 +110,7 @@ static unsigned numeric_consist1(void) * 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 original bug in CLN was finally killed on September 2nd. */ -static unsigned numeric_consist2(void) +static unsigned exam_numeric2(void) { unsigned result = 0; @@ -171,7 +149,7 @@ static unsigned numeric_consist2(void) /* Assorted tests to ensure some crucial functions behave exactly as specified * in the documentation. */ -static unsigned numeric_consist3(void) +static unsigned exam_numeric3(void) { unsigned result = 0; numeric calc_rem, calc_quo; @@ -289,7 +267,7 @@ static unsigned numeric_consist3(void) /* Now we perform some less trivial checks about several functions which should * return exact numbers if possible. */ -static unsigned numeric_consist4(void) +static unsigned exam_numeric4(void) { unsigned result = 0; bool passed; @@ -323,23 +301,23 @@ static unsigned numeric_consist4(void) return result; } -unsigned numeric_consist(void) +unsigned exam_numeric(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(); - + cout << "examining consistency of numeric types" << flush; + clog << "----------consistency of numeric types:" << endl; + + result += exam_numeric1(); cout << '.' << flush; + result += exam_numeric2(); cout << '.' << flush; + result += exam_numeric3(); cout << '.' << flush; + result += exam_numeric4(); cout << '.' << flush; + if (!result) { - cout << " passed "; + cout << " passed " << endl; clog << "(no output)" << endl; } else { - cout << " failed "; + cout << " failed " << endl; } return result; diff --git a/check/paranoia_check.cpp b/check/exam_paranoia.cpp similarity index 86% rename from check/paranoia_check.cpp rename to check/exam_paranoia.cpp index 125fb733..7ad2cad9 100644 --- a/check/paranoia_check.cpp +++ b/check/exam_paranoia.cpp @@ -1,4 +1,4 @@ -/** @file paranoia_check.cpp +/** @file exam_paranoia.cpp * * This set of tests checks for some of GiNaC's oopses which showed up during * development. Things were evaluated wrongly and so. Such a sick behaviour @@ -23,16 +23,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "ginac.h" - -#ifndef NO_NAMESPACE_GINAC -using namespace GiNaC; -#endif // ndef NO_NAMESPACE_GINAC +#include "exams.h" // The very first pair of historic problems had its roots in power.cpp and was // finally resolved on April 27th 1999. (Fixing the first on April 23rd // actually introduced the second.) -static unsigned paranoia_check1(void) +static unsigned exam_paranoia1(void) { unsigned result = 0; symbol x("x"), y("y"), z("z"); @@ -63,7 +59,7 @@ static unsigned paranoia_check1(void) // 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) +static unsigned exam_paranoia2(void) { unsigned result = 0; symbol x("x"), y("y"), z("z"); @@ -99,7 +95,7 @@ static unsigned paranoia_check2(void) // The third bug was introduced on May 18th 1999, 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) +static unsigned exam_paranoia3(void) { unsigned result = 0; symbol x("x"), y("y"); @@ -128,7 +124,7 @@ static unsigned paranoia_check3(void) } // The fourth bug was also discovered on May 19th 1999 and fixed immediately: -static unsigned paranoia_check4(void) +static unsigned exam_paranoia4(void) { unsigned result = 0; symbol x("x"); @@ -153,7 +149,7 @@ static unsigned paranoia_check4(void) } // The fifth oops was discovered on May 20th 1999 and fixed a day later: -static unsigned paranoia_check5(void) +static unsigned exam_paranoia5(void) { unsigned result = 0; symbol x("x"), y("y"); @@ -172,7 +168,7 @@ static unsigned paranoia_check5(void) } // This one was discovered on Jun 1st 1999 and fixed the same day: -static unsigned paranoia_check6(void) +static unsigned exam_paranoia6(void) { unsigned result = 0; symbol x("x"); @@ -190,7 +186,7 @@ static unsigned paranoia_check6(void) // This one was introduced on June 1st 1999 by some aggressive manual // optimization. Discovered and fixed on June 2nd. -static unsigned paranoia_check7(void) +static unsigned exam_paranoia7(void) { unsigned result = 0; symbol x("x"), y("y"); @@ -210,7 +206,7 @@ static unsigned paranoia_check7(void) // This one was a result of the rewrite of mul::max_coefficient when we // introduced the overall_coefficient field in expairseq objects on Oct 1st // 1999. Fixed on Oct 4th. -static unsigned paranoia_check8(void) +static unsigned exam_paranoia8(void) { unsigned result = 0; symbol x("x"); @@ -236,7 +232,7 @@ static unsigned paranoia_check8(void) // Z[X]. multiply_lcm() forgot to multiply the x-linear term with the LCM of // the coefficient's denominators (2 in this case). Introduced on Jan 25th // 2000 and fixed on Jan 31th. -static unsigned paranoia_check9(void) +static unsigned exam_paranoia9(void) { unsigned result = 0; symbol x("x"); @@ -255,7 +251,7 @@ static unsigned paranoia_check9(void) // and on Feb 13th 2000 I found out that things like 2^(3/2) throw an exception // "power::eval(): pow(0,0) is undefined" instead of simplifying to 2*2^(1/2). // It was fixed that same day. -static unsigned paranoia_check10(void) +static unsigned exam_paranoia10(void) { unsigned result = 0; @@ -280,7 +276,7 @@ static unsigned paranoia_check10(void) // add::normal() forgot to multiply the denominator of the overall_coeff of // its expanded and normalized children with the denominator of the expanded // child (did you get this? Well, never mind...). Fixed on Feb 21th 2000. -static unsigned paranoia_check11(void) +static unsigned exam_paranoia11(void) { unsigned result = 0; symbol x("x"); @@ -296,31 +292,31 @@ static unsigned paranoia_check11(void) return result; } -unsigned paranoia_check(void) +unsigned exam_paranoia(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(); - result += paranoia_check9(); - result += paranoia_check10(); - result += paranoia_check11(); - + + cout << "examining several historic failures just out of paranoia" << flush; + clog << "----------several historic failures:" << endl; + + result += exam_paranoia1(); cout << '.' << flush; + result += exam_paranoia2(); cout << '.' << flush; + result += exam_paranoia3(); cout << '.' << flush; + result += exam_paranoia4(); cout << '.' << flush; + result += exam_paranoia5(); cout << '.' << flush; + result += exam_paranoia6(); cout << '.' << flush; + result += exam_paranoia7(); cout << '.' << flush; + result += exam_paranoia8(); cout << '.' << flush; + result += exam_paranoia9(); cout << '.' << flush; + result += exam_paranoia10(); cout << '.' << flush; + result += exam_paranoia11(); cout << '.' << flush; + if (!result) { - cout << " passed "; + cout << " passed " << endl; clog << "(no output)" << endl; } else { - cout << " failed "; + cout << " failed " << endl; } - + return result; } diff --git a/check/poly_gcd.cpp b/check/exam_polygcd.cpp similarity index 87% rename from check/poly_gcd.cpp rename to check/exam_polygcd.cpp index 0e6780c8..34aea62a 100644 --- a/check/poly_gcd.cpp +++ b/check/exam_polygcd.cpp @@ -1,4 +1,4 @@ -/** @file poly_gcd.cpp +/** @file exam_polygcd.cpp * * Some test with polynomial GCD calculations. See also the checks for * rational function normalization in normalization.cpp. */ @@ -21,13 +21,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "ginac.h" +#include "exams.h" -#ifndef NO_NAMESPACE_GINAC -using namespace GiNaC; -#endif // ndef NO_NAMESPACE_GINAC - -const int MAX_VARIABLES = 5; +const int MAX_VARIABLES = 3; static symbol x("x"), z("z"); static symbol y[MAX_VARIABLES]; @@ -215,7 +211,7 @@ static unsigned poly_gcd7(void) ex p = x - y * z + 1; ex q = x - y + z * 3; - for (int j=1; j<=3; j++) { + for (int j=1; j<=MAX_VARIABLES; j++) { for (int k=j+1; k<=4; k++) { ex d = pow(p, j) * pow(q, j); ex f = pow(p, j) * pow(q, k); @@ -230,28 +226,29 @@ static unsigned poly_gcd7(void) return 0; } -unsigned poly_gcd(void) +unsigned exam_polygcd(void) { unsigned result = 0; - - cout << "checking polynomial GCD computation..." << flush; - clog << "---------polynomial GCD computation:" << endl; - - result += poly_gcd1(); - result += poly_gcd2(); - result += poly_gcd3(); -// result += poly_gcd3p(); // takes extremely long (PRS "worst" case) - result += poly_gcd4(); - result += poly_gcd5(); - result += poly_gcd5p(); - result += poly_gcd6(); - result += poly_gcd7(); - + + cout << "examining polynomial GCD computation" << flush; + clog << "----------polynomial GCD computation:" << endl; + + result += poly_gcd1(); cout << '.' << flush; + result += poly_gcd2(); cout << '.' << flush; + result += poly_gcd3(); cout << '.' << flush; + result += poly_gcd3p(); cout << '.' << flush; // takes extremely long (PRS "worst" case) + result += poly_gcd4(); cout << '.' << flush; + result += poly_gcd5(); cout << '.' << flush; + result += poly_gcd5p(); cout << '.' << flush; + result += poly_gcd6(); cout << '.' << flush; + result += poly_gcd7(); cout << '.' << flush; + if (!result) { - cout << " passed "; + cout << " passed " << endl; clog << "(no output)" << endl; } else { - cout << " failed "; + cout << " failed " << endl; } + return result; } diff --git a/check/powerlaws.cpp b/check/exam_powerlaws.cpp similarity index 93% rename from check/powerlaws.cpp rename to check/exam_powerlaws.cpp index e885369c..74e95de8 100644 --- a/check/powerlaws.cpp +++ b/check/exam_powerlaws.cpp @@ -1,4 +1,4 @@ -/** @file powerlaws.cpp +/** @file exam_powerlaws.cpp * * Tests for power laws. You shouldn't try to draw much inspiration from * this code, it is a sanity check rather deeply rooted in GiNaC's classes. */ @@ -21,13 +21,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "ginac.h" +#include "exams.h" -#ifndef NO_NAMESPACE_GINAC -using namespace GiNaC; -#endif // ndef NO_NAMESPACE_GINAC - -static unsigned powerlaws1(void) +static unsigned exam_powerlaws1(void) { // (x^a)^b = x^(a*b) @@ -103,7 +99,7 @@ static unsigned powerlaws1(void) return 0; } -static unsigned powerlaws2(void) +static unsigned exam_powerlaws2(void) { // (a*x)^b = a^b * x^b @@ -201,7 +197,7 @@ static unsigned powerlaws2(void) return 0; } -static unsigned powerlaws3(void) +static unsigned exam_powerlaws3(void) { // numeric evaluation @@ -240,7 +236,7 @@ static unsigned powerlaws3(void) return 0; } -static unsigned powerlaws4(void) +static unsigned exam_powerlaws4(void) { // test for mul::eval() @@ -264,23 +260,24 @@ static unsigned powerlaws4(void) return 0; } -unsigned powerlaws(void) +unsigned exam_powerlaws(void) { unsigned result = 0; - cout << "checking power laws..." << flush; - clog << "---------power laws:" << endl; + cout << "examining power laws" << flush; + clog << "----------power laws:" << endl; - result += powerlaws1(); - result += powerlaws2(); - result += powerlaws3(); - result += powerlaws4(); + result += exam_powerlaws1(); cout << '.' << flush; + result += exam_powerlaws2(); cout << '.' << flush; + result += exam_powerlaws3(); cout << '.' << flush; + result += exam_powerlaws4(); cout << '.' << flush; if (!result) { - cout << " passed "; + cout << " passed " << endl; clog << "(no output)" << endl; } else { - cout << " failed "; + cout << " failed " << endl; } + return result; } diff --git a/check/series_expansion.cpp b/check/exam_pseries.cpp similarity index 90% rename from check/series_expansion.cpp rename to check/exam_pseries.cpp index 4cd16970..efcc0fc1 100644 --- a/check/series_expansion.cpp +++ b/check/exam_pseries.cpp @@ -1,4 +1,4 @@ -/** @file series_expansion.cpp +/** @file exam_pseries.cpp * * Series expansion test (Laurent and Taylor series). */ @@ -20,11 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "ginac.h" - -#ifndef NO_NAMESPACE_GINAC -using namespace GiNaC; -#endif // ndef NO_NAMESPACE_GINAC +#include "exams.h" static symbol x("x"); @@ -43,7 +39,7 @@ static unsigned check_series(const ex &e, const ex &point, const ex &d, int orde } // Series expansion -static unsigned series1(void) +static unsigned exam_series1(void) { unsigned result = 0; ex e, d; @@ -106,7 +102,7 @@ static unsigned series1(void) } // Series addition -static unsigned series2(void) +static unsigned exam_series2(void) { unsigned result = 0; ex e, d; @@ -119,7 +115,7 @@ static unsigned series2(void) } // Series multiplication -static unsigned series3(void) +static unsigned exam_series3(void) { unsigned result = 0; ex e, d; @@ -132,7 +128,7 @@ static unsigned series3(void) } // Order term handling -static unsigned series4(void) +static unsigned exam_series4(void) { unsigned result = 0; ex e, d; @@ -152,7 +148,7 @@ static unsigned series4(void) } // Series of special functions -static unsigned series5(void) +static unsigned exam_series5(void) { unsigned result = 0; ex e, d; @@ -199,24 +195,24 @@ static unsigned series5(void) return result; } -unsigned series_expansion(void) +unsigned exam_pseries(void) { unsigned result = 0; - cout << "checking series expansion..." << flush; - clog << "---------series expansion:" << endl; + cout << "examining series expansion" << flush; + clog << "----------series expansion:" << endl; - result += series1(); - result += series2(); - result += series3(); - result += series4(); - result += series5(); + result += exam_series1(); cout << '.' << flush; + result += exam_series2(); cout << '.' << flush; + result += exam_series3(); cout << '.' << flush; + result += exam_series4(); cout << '.' << flush; + result += exam_series5(); cout << '.' << flush; if (!result) { - cout << " passed "; + cout << " passed " << endl; clog << "(no output)" << endl; } else { - cout << " failed "; + cout << " failed " << endl; } return result; } diff --git a/check/exams.cpp b/check/exams.cpp new file mode 100644 index 00000000..31b5cf7f --- /dev/null +++ b/check/exams.cpp @@ -0,0 +1,121 @@ +/** @file exams.cpp + * + * Main program that calls all individual exams. */ + +/* + * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "exams.h" + +int main() +{ + unsigned result = 0; + + try { + result += exam_paranoia(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + try { + result += exam_numeric(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + try { + result += exam_powerlaws(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + try { + result += exam_differentiation(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + try { + result += exam_polygcd(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + try { + result += exam_normalization(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + try { + result += exam_pseries(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + try { + result += exam_matrices(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + try { + result += exam_lsolve(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + try { + result += exam_noncommut(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + try { + result += exam_misc(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + if (result) { + cout << "Error: something went wrong. "; + if (result == 1) { + cout << "(one failure)" << endl; + } else { + cout << "(" << result << " individual failures)" << endl; + } + cout << "please check exam.out against exam.ref for more details." + << endl << "happy debugging!" << endl; + } + + return result; +} diff --git a/check/exams.h b/check/exams.h new file mode 100644 index 00000000..3582d538 --- /dev/null +++ b/check/exams.h @@ -0,0 +1,45 @@ +/** @file exams.h + * + * Prototypes for all individual exams. */ + +/* + * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef EXAMS_H +#define EXAMS_H + +#include "ginac.h" + +#ifndef NO_NAMESPACE_GINAC +using namespace GiNaC; +#endif // ndef NO_NAMESPACE_GINAC + +// prototypes for all individual checks should be unsigned fcn(): +unsigned exam_paranoia(); +unsigned exam_numeric(); +unsigned exam_powerlaws(); +unsigned exam_differentiation(); +unsigned exam_polygcd(); +unsigned exam_normalization(); +unsigned exam_pseries(); +unsigned exam_matrices(); +unsigned exam_lsolve(); +unsigned exam_noncommut(); +unsigned exam_misc(); + +#endif // ndef EXAMS_H diff --git a/check/exams.ref b/check/exams.ref new file mode 100644 index 00000000..e15e241a --- /dev/null +++ b/check/exams.ref @@ -0,0 +1,22 @@ +----------several historic failures: +(no output) +----------consistency of numeric types: +(no output) +----------power laws: +(no output) +----------symbolic differentiation: +(no output) +----------polynomial GCD computation: +(no output) +----------rational function normalization: +(no output) +----------series expansion: +(no output) +----------symbolic matrix manipulations: +(no output) +----------linear solve: +(no output) +----------behaviour of noncommutative objects: +(no output) +----------miscellaneous other things: +(no output) diff --git a/check/genex.cpp b/check/genex.cpp new file mode 100644 index 00000000..77ea18fd --- /dev/null +++ b/check/genex.cpp @@ -0,0 +1,58 @@ +/** @file genex.cpp + * + * Provides some routines for generating expressions that are later used as input + * in the consistency checks. */ + +/* + * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// For rand() and friends: +#include + +#include "ginac.h" + +#ifndef NO_NAMESPACE_GINAC +using namespace GiNaC; +#endif // ndef NO_NAMESPACE_GINAC + +/* Create a dense univariate random polynomial in x. + * (of the form 9 - 22*a - 17*a^2 + 14*a^3 + 7*a^4 + 7a^5 if degree==5) */ +const ex +dense_univariate_poly(const symbol & x, unsigned degree) +{ + ex unipoly; + + for (unsigned i=0; i<=degree; ++i) + unipoly += numeric((rand()-RAND_MAX/2))*pow(x,i); + + return unipoly; +} + +/* Create a dense bivariate random polynomial in x1 and x2. + * (of the form 9 + 52*x1 - 27*x1^2 + 84*x2 + 7*x2^2 - 12*x1*x2 if degree ==2) */ +const ex +dense_bivariate_poly(const symbol & x1, const symbol & x2, unsigned degree) +{ + ex bipoly; + + for (unsigned i1=0; i1<=degree; ++i1) + for (unsigned i2=0; i2<=degree-i1; ++i2) + bipoly += numeric((rand()-RAND_MAX/2))*pow(x1,i1)*pow(x2,i2); + + return bipoly; +} diff --git a/check/numeric_output.cpp b/check/numeric_output.cpp deleted file mode 100644 index 6b3a2599..00000000 --- a/check/numeric_output.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/** @file numeric_output.cpp - * - * Test output of numeric types. */ - -/* - * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ginac.h" - -#ifndef NO_NAMESPACE_GINAC -using namespace GiNaC; -#endif // ndef NO_NAMESPACE_GINAC - -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 = 222; - 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/result.ref b/check/result.ref deleted file mode 100644 index b4fa5871..00000000 --- a/check/result.ref +++ /dev/null @@ -1,30 +0,0 @@ ----------several ex-bugs just out of pure paranoia: -(no output) ----------output of numeric types: -Using 222 digits -Pi evalfs to: 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648235L0 -Catalan evalfs to: 0.915965594177219015054603514932384110774149374281672134266498119621763019776254769479356512926115106248574422619196199579035898803325859059431594737481158406995332028773319460519038727478164087865909024706484152163000228727640942388L0 -EulerGamma evalfs to: 0.577215664901532860606512090082402431042159335939923598805767234884867726777664670936947063291746749514631447249807082480960504014486542836224173997644923536253500333742937337737673942792595258247094916008735203948165670853233151777L0 -Complex integers: {(0,0)=0} {(1,0)=1} {(1,1)=1+I} {(0,1)=I} {(-1,1)=-1+I} {(-1,0)=-1} {(-1,-1)=-1-I} {(0,-1)=-I} {(1,-1)=1-I} ----------consistency of numeric types: -(no output) ----------power laws: -(no output) ----------commutative expansion and substitution: -(no output) ----------consistency of symbolic functions: -(no output) ----------symbolic differentiation: -(no output) ----------polynomial GCD computation: -(no output) ----------rational function normalization: -(no output) ----------symbolic matrix manipulations: -(no output) ----------linear solve: -(no output) ----------series expansion: -(no output) ----------manipulations of lortensor objects: -(no output) diff --git a/check/run_checks b/check/run_checks index 8d3adcbb..92ba1a2b 100755 --- a/check/run_checks +++ b/check/run_checks @@ -1,5 +1,4 @@ #! /bin/sh -echo "Running checks..." -./check_ginac 2>result.out -echo "Comparing output..." -cmp ${srcdir}/result.ref result.out +echo "GiNaC will now run through some rather costly consistency checks:" +./checks 2>checks.out +cmp ${srcdir}/checks.ref checks.out diff --git a/check/run_exams b/check/run_exams new file mode 100755 index 00000000..8c8efa59 --- /dev/null +++ b/check/run_exams @@ -0,0 +1,4 @@ +#! /bin/sh +echo "GiNaC will now take an exam with specific input (like a pupils' exam):" +./exams 2>exams.out +cmp ${srcdir}/exams.ref exams.out diff --git a/check/run_times b/check/run_times new file mode 100755 index 00000000..3687f1ef --- /dev/null +++ b/check/run_times @@ -0,0 +1,4 @@ +#! /bin/sh +echo "GiNaC will now run through some basic timings:" +./times 2>times.out +cmp ${srcdir}/times.ref times.out diff --git a/check/time_dennyfliegner.cpp b/check/time_dennyfliegner.cpp new file mode 100644 index 00000000..23c7a953 --- /dev/null +++ b/check/time_dennyfliegner.cpp @@ -0,0 +1,96 @@ +/** @file time_dennyfliegner.cpp + * + * The first test routine implements Denny Fliegner's quick consistency check: + * 1) e = (a0 + a1 + a2 + a3 + ...)^2, in expanded form + * 2) substitute a0 by (-a2 - a3 - ...) in e + * 3) expand e + * after which e should be just a1^2. */ + +/* + * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "times.h" + +#define VECSIZE 200 + +static unsigned expand_subs(unsigned size) +{ + unsigned result = 0; + symbol a1("a1"); + symbol a[VECSIZE]; + ex e, aux; + + a[1] = a1; + for (unsigned i=0; i sizes; + vector times; + timer rolex; + + sizes.push_back(40); + sizes.push_back(60); + sizes.push_back(100); + sizes.push_back(150); + + for (vector::iterator i=sizes.begin(); i!=sizes.end(); ++i) { + rolex.start(); + result += expand_subs(*i); cout << '.' << flush; + times.push_back(rolex.read()); + } + + if (!result) { + cout << " passed "; + clog << "(no output)" << endl; + } else { + cout << " failed "; + } + // print the report: + cout << endl << " size: "; + for (vector::iterator i=sizes.begin(); i!=sizes.end(); ++i) { + cout << '\t' << (*i); + } + cout << endl << " time/s:"; + for (vector::iterator i=times.begin(); i!=times.end(); ++i) { + cout << '\t' << (*i); + } + cout << endl; + + return result; +} diff --git a/check/time_gammaseries.cpp b/check/time_gammaseries.cpp new file mode 100644 index 00000000..afc9f530 --- /dev/null +++ b/check/time_gammaseries.cpp @@ -0,0 +1,86 @@ +/** @file time_gammaseries.cpp + * + * Some timings on series expansion of the gamma function around a pole. */ + +/* + * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "times.h" + +unsigned gammaseries(unsigned order) +{ + unsigned result = 0; + symbol x; + + ex myseries = series(gamma(x),x,0,order); + // compute the last coefficient numerically: + ex last_coeff = myseries.coeff(x,order-1).evalf(); + // compute a bound for that coefficient using a variation of the leading + // term in Stirling's formula: + ex bound = evalf(exp(ex(-.57721566490153286*(order-1)))/(order-1)); + if (evalf(abs((last_coeff-pow(-1,order))/bound)) > numeric(1)) { + clog << "The " << order-1 + << "th order coefficient in the power series expansion of gamma(0) was erroneously found to be " + << last_coeff << ", violating a simple estimate." << endl; + ++result; + } + + return result; +} + +unsigned time_gammaseries(void) +{ + unsigned result = 0; + + cout << "timing Laurent series expansion of gamma function" << flush; + clog << "-------Laurent series expansion of gamma function:" << endl; + + vector sizes; + vector times; + timer omega; + + sizes.push_back(10); + sizes.push_back(15); + sizes.push_back(20); + sizes.push_back(25); + + for (vector::iterator i=sizes.begin(); i!=sizes.end(); ++i) { + omega.start(); + result += gammaseries(*i); cout << '.' << flush; + times.push_back(omega.read()); + } + + if (!result) { + cout << " passed "; + clog << "(no output)" << endl; + } else { + cout << " failed "; + } + // print the report: + cout << endl << " order: "; + for (vector::iterator i=sizes.begin(); i!=sizes.end(); ++i) { + cout << '\t' << (*i); + } + cout << endl << " time/s:"; + for (vector::iterator i=times.begin(); i!=times.end(); ++i) { + cout << '\t' << (*i); + } + cout << endl; + + return result; +} diff --git a/check/fcntimer.cpp b/check/timer.cpp similarity index 63% rename from check/fcntimer.cpp rename to check/timer.cpp index b040c7e6..c4c21a30 100644 --- a/check/fcntimer.cpp +++ b/check/timer.cpp @@ -1,6 +1,6 @@ -/** @file fcntimer.cpp +/** @file timer.cpp * - * Function execution timer. */ + * A simple stop watch class. */ /* * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany @@ -20,33 +20,47 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "times.h" -#include -#include +timer::timer(void) : on(false) +{ + getrusage(RUSAGE_SELF, &used1); + getrusage(RUSAGE_SELF, &used2); +} +void timer::start(void) +{ + on = true; + getrusage(RUSAGE_SELF, &used1); + getrusage(RUSAGE_SELF, &used2); +} -// 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()) +void timer::stop(void) { - unsigned fcnresult; - struct rusage used1, used2; - double elapsed; + on = false; + getrusage(RUSAGE_SELF, &used2); +} - // time the execution of the function: +void timer::reset(void) +{ getrusage(RUSAGE_SELF, &used1); - fcnresult = fcn(); getrusage(RUSAGE_SELF, &used2); +} - // add elapsed user and system time in microseconds: +double timer::read(void) +{ + double elapsed; + if (this->running()) + getrusage(RUSAGE_SELF, &used2); 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); + // round to 10ms for safety: + return 0.01*int(elapsed*100+0.5); +} - printf("(%.2fs)\n", elapsed); - - return fcnresult; +bool timer::running(void) +{ + return on; } diff --git a/check/main.cpp b/check/times.cpp similarity index 56% rename from check/main.cpp rename to check/times.cpp index d3fbea98..d2b40e81 100644 --- a/check/main.cpp +++ b/check/times.cpp @@ -1,6 +1,6 @@ -/** @file main.cpp +/** @file times.cpp * - * Main program that calls all individual tests. */ + * Main program that calls the individual timings. */ /* * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany @@ -23,43 +23,38 @@ #include #include -#include "check.h" +#include "times.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(linear_solve); - result += fcntimer(series_expansion); - result += fcntimer(lortensor_check); - } + for (int i=0; i<1; ++i) + result += time_dennyfliegner(); } catch (const exception &e) { - cout << "error: caught an exception: " << e.what() << endl; - result++; + cout << "Error: caught exception " << e.what() << endl; + ++result; + } + + try { + for (int i=0; i<1; ++i) + result += time_gammaseries(); + } catch (const exception &e) { + cout << "Error: caught exception " << e.what() << endl; + ++result; } if (result) { - cout << "error: something went wrong. "; + 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." + cout << "please check times.out against times.ref for more details." << endl << "happy debugging!" << endl; } - + return result; } diff --git a/check/times.h b/check/times.h new file mode 100644 index 00000000..bb54399e --- /dev/null +++ b/check/times.h @@ -0,0 +1,53 @@ +/** @file times.h + * + * Prototypes for all individual timings. */ + +/* + * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef CHECKS_H +#define CHECKS_H + +#include +#include +#include + +#include "ginac.h" + +#ifndef NO_NAMESPACE_GINAC +using namespace GiNaC; +#endif // ndef NO_NAMESPACE_GINAC + +class timer { +public: + timer(); + void start(void); + void stop(void); + void reset(void); + double read(void); + bool running(void); +private: + bool on; + struct rusage used1, used2; +}; + +// prototypes for all individual timings should be unsigned fcn(): +unsigned time_dennyfliegner(); +unsigned time_gammaseries(); + +#endif // ndef CHECKS_H diff --git a/check/times.ref b/check/times.ref new file mode 100644 index 00000000..4aef1c99 --- /dev/null +++ b/check/times.ref @@ -0,0 +1,4 @@ +-------commutative expansion and substitution: +(no output) +-------Laurent series expansion of gamma function: +(no output) diff --git a/cint/Makefile.in b/cint/Makefile.in index 43dc2d8f..a494a339 100644 --- a/cint/Makefile.in +++ b/cint/Makefile.in @@ -84,6 +84,7 @@ GINSH_LIBS = @GINSH_LIBS@ LATEX = @LATEX@ LEX = @LEX@ LIBGINACCINT = @LIBGINACCINT@ +LIBTERMCAP = @LIBTERMCAP@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LT_AGE = @LT_AGE@ diff --git a/config.h.in b/config.h.in index f4d7fb17..8709ddce 100644 --- a/config.h.in +++ b/config.h.in @@ -18,6 +18,9 @@ /* The number of bytes in a long long. */ #undef SIZEOF_LONG_LONG +/* Define if you have the tgetent function. */ +#undef HAVE_TGETENT + /* Define if you have the header file. */ #undef HAVE_ALGORITHM diff --git a/doc/Makefile.in b/doc/Makefile.in index e153dbe7..f7d7934f 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -84,6 +84,7 @@ GINSH_LIBS = @GINSH_LIBS@ LATEX = @LATEX@ LEX = @LEX@ LIBGINACCINT = @LIBGINACCINT@ +LIBTERMCAP = @LIBTERMCAP@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LT_AGE = @LT_AGE@ diff --git a/doc/reference/Makefile.in b/doc/reference/Makefile.in index 3ed3518b..021b10ea 100644 --- a/doc/reference/Makefile.in +++ b/doc/reference/Makefile.in @@ -87,6 +87,7 @@ GINSH_LIBS = @GINSH_LIBS@ LATEX = @LATEX@ LEX = @LEX@ LIBGINACCINT = @LIBGINACCINT@ +LIBTERMCAP = @LIBTERMCAP@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LT_AGE = @LT_AGE@ diff --git a/doc/tutorial/Makefile.in b/doc/tutorial/Makefile.in index 0964c1aa..ddb71492 100644 --- a/doc/tutorial/Makefile.in +++ b/doc/tutorial/Makefile.in @@ -86,6 +86,7 @@ GINSH_LIBS = @GINSH_LIBS@ LATEX = @LATEX@ LEX = @LEX@ LIBGINACCINT = @LIBGINACCINT@ +LIBTERMCAP = @LIBTERMCAP@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LT_AGE = @LT_AGE@ diff --git a/ginac/Makefile.in b/ginac/Makefile.in index 04081088..e4eca61e 100644 --- a/ginac/Makefile.in +++ b/ginac/Makefile.in @@ -84,6 +84,7 @@ GINSH_LIBS = @GINSH_LIBS@ LATEX = @LATEX@ LEX = @LEX@ LIBGINACCINT = @LIBGINACCINT@ +LIBTERMCAP = @LIBTERMCAP@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LT_AGE = @LT_AGE@ diff --git a/ginac/inifcns.cpp b/ginac/inifcns.cpp index bc401f47..55da24d0 100644 --- a/ginac/inifcns.cpp +++ b/ginac/inifcns.cpp @@ -212,10 +212,10 @@ ex lsolve(const ex &eqns, const ex &symbols) matrix vars(symbols.nops(),1); for (unsigned r=0; r +#include #include #include "matrix.h" #include "archive.h" #include "utils.h" #include "debugmsg.h" +#include "numeric.h" #ifndef NO_NAMESPACE_GINAC namespace GiNaC { @@ -301,23 +303,21 @@ ex matrix::evalf(int level) const int matrix::compare_same_type(const basic & other) const { GINAC_ASSERT(is_exactly_of_type(other, matrix)); - const matrix & o=static_cast(const_cast(other)); + const matrix & o = static_cast(const_cast(other)); // compare number of rows - if (row != o.rows()) { + if (row != o.rows()) return row < o.rows() ? -1 : 1; - } // compare number of columns - if (col != o.cols()) { + if (col != o.cols()) return col < o.cols() ? -1 : 1; - } // equal number of rows and columns, compare individual elements int cmpval; for (unsigned r=0; r -int permutation_sign(vector s) -{ - if (s.size() < 2) - return 0; - int sigma=1; - for (typename vector::iterator i=s.begin(); i!=s.end()-1; ++i) { - for (typename vector::iterator j=i+1; j!=s.end(); ++j) { - if (*i == *j) - return 0; - if (*i > *j) { - iter_swap(i,j); - sigma = -sigma; - } - } - } - return sigma; -} - -/** Determinant built by application of the full permutation group. This - * routine is only called internally by matrix::determinant(). */ -ex determinant_symbolic_perm(const matrix & M) -{ - GINAC_ASSERT(M.rows()==M.cols()); // cannot happen, just in case... - - if (M.rows()==1) { // speed things up - return M(0,0); - } - - ex det; - ex term; - vector sigma(M.cols()); - for (unsigned i=0; i" << sol.ffe_get(c,1) << endl; - } - */ - - // cout << "sol=" << sol << endl; #ifdef DO_GINAC_ASSERT // test solution with echelon matrix for (unsigned r=1; r<=m; ++r) { - ex e=0; - for (unsigned c=1; c<=n; ++c) { - e=e+a.ffe_get(r,c)*sol.ffe_get(c,1); - } + ex e = 0; + for (unsigned c=1; c<=n; ++c) + e = e+a.ffe_get(r,c)*sol.ffe_get(c,1); if (!(e-b.ffe_get(r,1)).normal().is_zero()) { cout << "e=" << e; cout << "b.ffe_get(" << r<<",1)=" << b.ffe_get(r,1) << endl; @@ -862,25 +729,24 @@ matrix matrix::fraction_free_elim(const matrix & vars, } GINAC_ASSERT((e-b.ffe_get(r,1)).normal().is_zero()); } - + // test solution with original matrix for (unsigned r=1; r<=m; ++r) { - ex e=0; - for (unsigned c=1; c<=n; ++c) { - e=e+ffe_get(r,c)*sol.ffe_get(c,1); - } + ex e = 0; + for (unsigned c=1; c<=n; ++c) + e = e+ffe_get(r,c)*sol.ffe_get(c,1); try { - if (!(e-rhs.ffe_get(r,1)).normal().is_zero()) { - cout << "e=" << e << endl; - e.printtree(cout); - ex en=e.normal(); - cout << "e.normal()=" << en << endl; - en.printtree(cout); - cout << "rhs.ffe_get(" << r<<",1)=" << rhs.ffe_get(r,1) << endl; - cout << "diff=" << (e-rhs.ffe_get(r,1)).normal() << endl; - } + if (!(e-rhs.ffe_get(r,1)).normal().is_zero()) { + cout << "e=" << e << endl; + e.printtree(cout); + ex en = e.normal(); + cout << "e.normal()=" << en << endl; + en.printtree(cout); + cout << "rhs.ffe_get(" << r<<",1)=" << rhs.ffe_get(r,1) << endl; + cout << "diff=" << (e-rhs.ffe_get(r,1)).normal() << endl; + } } catch (...) { - ex xxx=e-rhs.ffe_get(r,1); + ex xxx = e - rhs.ffe_get(r,1); cerr << "xxx=" << xxx << endl << endl; } GINAC_ASSERT((e-rhs.ffe_get(r,1)).normal().is_zero()); @@ -888,76 +754,281 @@ matrix matrix::fraction_free_elim(const matrix & vars, #endif // def DO_GINAC_ASSERT return sol; -} +} + +/** Solve a set of equations for an m x n matrix. + * + * @param vars n x p matrix + * @param rhs m x p matrix + * @exception logic_error (incompatible matrices) + * @exception runtime_error (singular matrix) */ +matrix matrix::solve(const matrix & vars, + const matrix & rhs) const +{ + if ((row != rhs.row) || (col != vars.row) || (rhs.col != vars.col)) + throw (std::logic_error("matrix::solve(): incompatible matrices")); -/** Solve simultaneous set of equations. */ -matrix matrix::solve(const matrix & v) const + throw (std::runtime_error("FIXME: need implementation.")); +} + +/** Old and obsolete interface: */ +matrix matrix::old_solve(const matrix & v) const { - if (!(row == col && col == v.row)) { + if ((v.row != col) || (col != v.row)) throw (std::logic_error("matrix::solve(): incompatible matrices")); - } - // build the extended matrix of *this with v attached to the right + // build the augmented matrix of *this with v attached to the right matrix tmp(row,col+v.col); for (unsigned r=0; rm[r*col+c]; + for (unsigned c=0; c0; --r) { + for (unsigned i=r; irow==1) + return m[0]; + if (this->row==2) + return (m[0]*m[3]-m[2]*m[1]); + if (this->row==3) + return ((m[4]*m[8]-m[5]*m[7])*m[0]- + (m[1]*m[8]-m[2]*m[7])*m[3]+ + (m[1]*m[5]-m[4]*m[2])*m[6]); - // assemble the solution matrix - exvector sol(v.row*v.col); - for (unsigned c=0; c=0; --r) { - sol[r*v.col+c] = tmp[r*tmp.col+c]; - for (unsigned i=r+1; irow-1,this->col-1); + // for (unsigned r1=0; r1row; ++r1) { + // // shortcut if element(r1,0) vanishes + // if (m[r1*col].is_zero()) + // continue; + // // assemble the minor matrix + // for (unsigned r=0; r,class ex> Rmap; + typedef map,class ex>::value_type Rmap_value; + Rmap A, B; + ex det; + vector Pkey; // Unique flipper counter for partitioning into minors + Pkey.reserve(this->col); + vector Mkey; // key for minor determinant (a subpartition of Pkey) + Mkey.reserve(this->col-1); + // initialize A with last column: + for (unsigned r=0; rcol; ++r) { + Pkey.erase(Pkey.begin(),Pkey.end()); + Pkey.push_back(r); + A.insert(Rmap_value(Pkey,m[this->col*r+this->col-1])); + } + // proceed from right to left through matrix + for (int c=this->col-2; c>=0; --c) { + Pkey.erase(Pkey.begin(),Pkey.end()); // don't change capacity + Mkey.erase(Mkey.begin(),Mkey.end()); + for (unsigned i=0; icol-c; ++i) + Pkey.push_back(i); + unsigned fc = 0; // controls logic for our strange flipper counter + do { + A.insert(Rmap_value(Pkey,_ex0())); + det = _ex0(); + for (unsigned r=0; rcol-c; ++r) { + // maybe there is nothing to do? + if (m[Pkey[r]*this->col+c].is_zero()) + continue; + // create the sorted key for all possible minors + Mkey.erase(Mkey.begin(),Mkey.end()); + for (unsigned i=0; icol-c; ++i) + if (i!=r) + Mkey.push_back(Pkey[i]); + // Fetch the minors and compute the new determinant + if (r%2) + det -= m[Pkey[r]*this->col+c]*A[Mkey]; + else + det += m[Pkey[r]*this->col+c]*A[Mkey]; } - } + // Store the new determinant at its place in B: + B.insert(Rmap_value(Pkey,det)); + // increment our strange flipper counter + for (fc=this->col-c; fc>0; --fc) { + ++Pkey[fc-1]; + if (Pkey[fc-1]col-c) + for (unsigned j=fc; jcol-c; ++j) + Pkey[j] = Pkey[j-1]+1; + } while(fc); + // change the role of A and B: + A = B; + B.clear(); } - return matrix(v.row, v.col, sol); + + return det; } -// protected +/** Determinant built by application of the full permutation group. This + * routine is only called internally by matrix::determinant(). */ +ex matrix::determinant_symbolic_perm(void) const +{ + if (rows()==1) // speed things up + return m[0]; + + ex det; + ex term; + vector sigma(col); + for (unsigned i=0; i 0) + sign = -sign; + for (unsigned r2=r1+1; r2m[r2*col+c] -= this->m[r2*col+r1]*this->m[r1*col+c]/this->m[r1*col+r1]; + for (unsigned c=0; c<=r1; ++c) + this->m[r2*col+c] = _ex0(); + } + } + return sign; +} /** Partial pivoting method. - * Usual pivoting returns the index to the element with the largest absolute - * value and swaps the current row with the one where the element was found. - * Here it does the same with the first non-zero element. (This works fine, - * but may be far from optimal for numerics.) */ -int matrix::pivot(unsigned ro) + * Usual pivoting (symbolic==false) returns the index to the element with the + * largest absolute value in column ro and swaps the current row with the one + * where the element was found. With (symbolic==true) it does the same thing + * with the first non-zero element. + * + * @param ro is the row to be inspected + * @param symbolic signal if we want the first non-zero element to be pivoted + * (true) or the one with the largest absolute value (false). + * @return 0 if no interchange occured, -1 if all are zero (usually signaling + * a degeneracy) and positive integer k means that rows ro and k were swapped. + */ +int matrix::pivot(unsigned ro, bool symbolic) { - unsigned k=ro; + unsigned k = ro; - for (unsigned r=ro; r maxn && + !tmp.is_zero()) { + maxn = tmp; + k = r; + } } } - if (m[k*col+ro].is_zero()) { + if (m[k*col+ro].is_zero()) return -1; - } if (k!=ro) { // swap rows + ensure_if_modifiable(); for (unsigned c=0; c #include @@ -65,7 +68,7 @@ protected: }; /** The remember table is organized like an n-fold associative cache - in a microprocessor. The table has a width of 's' (which is rounded + in a microprocessor. The table has a width of 's' (which is rounded to table_size, some power of 2 near 's', internally) and a depth of 'as' (unless you choose that entries are never discarded). The place where an entry is stored depends on the hashvalue of the parameters of the @@ -97,3 +100,5 @@ protected: #ifndef NO_NAMESPACE_GINAC } // namespace GiNaC #endif // ndef NO_NAMESPACE_GINAC + +#endif // ndef __GINAC_REMEMBER_H__ diff --git a/ginac/utils.h b/ginac/utils.h index fa6f54a5..7018bc95 100644 --- a/ginac/utils.h +++ b/ginac/utils.h @@ -138,6 +138,26 @@ OutputIterator mymerge3(InputIterator1 first1, InputIterator1 last1, } } +// Compute the sign of a permutation of a vector of things. +template +int permutation_sign(vector s) +{ + if (s.size() < 2) + return 0; + int sigma = 1; + for (typename vector::iterator i=s.begin(); i!=s.end()-1; ++i) { + for (typename vector::iterator j=i+1; j!=s.end(); ++j) { + if (*i == *j) + return 0; + if (*i > *j) { + iter_swap(i,j); + sigma = -sigma; + } + } + } + return sigma; +} + // Collection of `construct on first use' wrappers for safely avoiding // internal object replication without running into the `static // initialization order fiasco'. This chest of numbers helps speed up diff --git a/ginsh/Makefile.in b/ginsh/Makefile.in index 52d94022..5bd33c8e 100644 --- a/ginsh/Makefile.in +++ b/ginsh/Makefile.in @@ -84,6 +84,7 @@ GINSH_LIBS = @GINSH_LIBS@ LATEX = @LATEX@ LEX = @LEX@ LIBGINACCINT = @LIBGINACCINT@ +LIBTERMCAP = @LIBTERMCAP@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LT_AGE = @LT_AGE@ diff --git a/tools/Makefile.in b/tools/Makefile.in index 13f92f31..0f42a2cd 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -84,6 +84,7 @@ GINSH_LIBS = @GINSH_LIBS@ LATEX = @LATEX@ LEX = @LEX@ LIBGINACCINT = @LIBGINACCINT@ +LIBTERMCAP = @LIBTERMCAP@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LT_AGE = @LT_AGE@ -- 2.44.0