From 97af29c12bb3074cfb4e674d71000f0712c51ba2 Mon Sep 17 00:00:00 2001 From: Richard Kreckel Date: Wed, 2 Feb 2000 18:49:29 +0000 Subject: [PATCH] - diff() is now only defined on classes ex and basic, where it handles higher derivatives. derivative() is now the method to be implemented by the user that does single derivatives, it is protected. - Implemented some very clumpsy automatic generation of ginaccint. It is ugly because we have to compile libginac without namespace GiNaC. - Fixed some wrong logic in numeric::power(). --- Makefile.in | 3 +- NEWS | 5 +- check/Makefile.in | 3 +- cint/Makefile.am | 17 +- cint/Makefile.in | 78 ++++--- cint/ginaccint.1 | 54 ++++- cint/{ginaccint.cpp => ginaccint.bin.cpp} | 65 +++--- cint/ginaccint.in | 13 ++ configure | 10 +- configure.in | 8 +- doc/Makefile.in | 3 +- doc/reference/Makefile.in | 3 +- doc/tutorial/Makefile.in | 3 +- doc/tutorial/ginac.texi | 32 +-- ginac/Makefile.am | 4 +- ginac/Makefile.in | 21 +- ginac/add.cpp | 8 + ginac/add.h | 2 +- ginac/basic.cpp | 31 +++ ginac/basic.h | 3 +- ginac/constant.cpp | 8 + ginac/constant.h | 2 +- ginac/container.pl | 4 +- ginac/diff.cpp | 253 ---------------------- ginac/ex.cpp | 15 ++ ginac/expairseq.cpp | 8 + ginac/expairseq.h | 2 +- ginac/function.pl | 39 +++- ginac/indexed.cpp | 7 + ginac/indexed.h | 2 +- ginac/inifcns_gamma.cpp | 30 +-- ginac/inifcns_trans.cpp | 96 ++++---- ginac/inifcns_zeta.cpp | 14 +- ginac/mul.cpp | 18 ++ ginac/mul.h | 2 +- ginac/ncmul.cpp | 7 + ginac/ncmul.h | 2 +- ginac/numeric.cpp | 37 ++-- ginac/numeric.h | 9 +- ginac/power.cpp | 21 +- ginac/power.h | 2 +- ginac/pseries.cpp | 26 +++ ginac/pseries.h | 3 +- ginac/symbol.cpp | 13 ++ ginac/symbol.h | 3 +- ginac/utils.h | 2 +- ginsh/Makefile.in | 3 +- 47 files changed, 518 insertions(+), 476 deletions(-) rename cint/{ginaccint.cpp => ginaccint.bin.cpp} (76%) create mode 100644 cint/ginaccint.in delete mode 100644 ginac/diff.cpp diff --git a/Makefile.in b/Makefile.in index e5818e33..a61a6e74 100644 --- a/Makefile.in +++ b/Makefile.in @@ -64,6 +64,7 @@ ARCHIVE_VERSION = @ARCHIVE_VERSION@ AS = @AS@ CC = @CC@ CINT = @CINT@ +CINTSYSDIR = @CINTSYSDIR@ CXX = @CXX@ CXXCPP = @CXXCPP@ DLLTOOL = @DLLTOOL@ @@ -358,7 +359,7 @@ distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ - cp -pr $$/$$file $(distdir)/$$file; \ + cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ diff --git a/NEWS b/NEWS index 5ac7e542..6dba3541 100644 --- a/NEWS +++ b/NEWS @@ -13,5 +13,8 @@ This file records noteworthy changes. info_flags::integer and -::cinteger work similarly, the same holds for types like info_flags::rational_polynomial. -0.5.0 () +0.5.0 (?? February 2000) * Expressions can be written ("archived") to files and read therefrom. +* Addition of GiNaC-cint, which lets you write complete programs in + an interactive shell-like manner in your favoured programming + language (C++). diff --git a/check/Makefile.in b/check/Makefile.in index 539353cc..ce230456 100644 --- a/check/Makefile.in +++ b/check/Makefile.in @@ -64,6 +64,7 @@ ARCHIVE_VERSION = @ARCHIVE_VERSION@ AS = @AS@ CC = @CC@ CINT = @CINT@ +CINTSYSDIR = @CINTSYSDIR@ CXX = @CXX@ CXXCPP = @CXXCPP@ DLLTOOL = @DLLTOOL@ @@ -253,7 +254,7 @@ distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ - cp -pr $$/$$file $(distdir)/$$file; \ + cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ diff --git a/cint/Makefile.am b/cint/Makefile.am index bc1690f8..0ad1bd50 100644 --- a/cint/Makefile.am +++ b/cint/Makefile.am @@ -1,19 +1,19 @@ ## Process this file with automake to produce Makefile.in -bin_PROGRAMS = ginaccint -noinst_LIBRARIES = libginac.a -ginaccint_SOURCES = ginaccint.cpp dummies.cpp dummies.h +bin_PROGRAMS = ginaccint.bin ginaccint +noinst_LTLIBRARIES = libginac.la +ginaccint_bin_SOURCES = ginaccint.bin.cpp dummies.cpp dummies.h man_MANS = ginaccint.1 # Build a modified library in the ginac-subdir and put it into the cint-subdir: -libginac.a: +libginac.la: (cd ../ginac && \ $(MAKE) clean; \ $(MAKE) CXXFLAGS="$$CXXFLAGS -DNO_NAMESPACE_GINAC" && \ $(MAKE) install-libLTLIBRARIES prefix=`pwd`/../cint libdir=`pwd`/../cint && \ $(MAKE) clean) -ginaccint: libginac.a ginaccint.cpp +ginaccint.bin: libginac.la ginaccint.bin.cpp $(MAKE) -f Makefile.makecint EXTRA_DIST = dummies.pl @@ -23,4 +23,9 @@ $(srcdir)/dummies.h $(srcdir)/dummies.cpp: $(srcdir)/dummies.pl cd $(srcdir) && perl dummies.pl # Force build of headers before compilation -$(srcdir)/ginaccint.cpp: $(srcdir)/dummies.h +$(srcdir)/ginaccint.bin.cpp: $(srcdir)/dummies.h + +# Force make clean to call Makecint's own Makefile +makecint_clean: + (if [ -f Makefile.makecint ]; then $(MAKE) -f Makefile.makecint clean; fi) +clean: makecint_clean diff --git a/cint/Makefile.in b/cint/Makefile.in index c1b96b2c..c4a8267e 100644 --- a/cint/Makefile.in +++ b/cint/Makefile.in @@ -64,6 +64,7 @@ ARCHIVE_VERSION = @ARCHIVE_VERSION@ AS = @AS@ CC = @CC@ CINT = @CINT@ +CINTSYSDIR = @CINTSYSDIR@ CXX = @CXX@ CXXCPP = @CXXCPP@ DLLTOOL = @DLLTOOL@ @@ -103,29 +104,34 @@ TUTORIAL_TARGETS = @TUTORIAL_TARGETS@ VERSION = @VERSION@ YACC = @YACC@ -bin_PROGRAMS = ginaccint -noinst_LIBRARIES = libginac.a -ginaccint_SOURCES = ginaccint.cpp dummies.cpp dummies.h +bin_PROGRAMS = ginaccint.bin ginaccint +noinst_LTLIBRARIES = libginac.la +ginaccint_bin_SOURCES = ginaccint.bin.cpp dummies.cpp dummies.h man_MANS = ginaccint.1 EXTRA_DIST = dummies.pl mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../config.h -CONFIG_CLEAN_FILES = -LIBRARIES = $(noinst_LIBRARIES) +CONFIG_CLEAN_FILES = ginaccint +LTLIBRARIES = $(noinst_LTLIBRARIES) DEFS = @DEFS@ -I. -I$(srcdir) -I.. CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ -libginac_a_LIBADD = -libginac_a_SOURCES = libginac.a.c -libginac_a_OBJECTS = libginac.a.o -AR = ar +libginac_la_LDFLAGS = +libginac_la_LIBADD = +libginac_la_SOURCES = libginac.la.c +libginac_la_OBJECTS = libginac.la.lo PROGRAMS = $(bin_PROGRAMS) -ginaccint_OBJECTS = ginaccint.o dummies.o +ginaccint_bin_OBJECTS = ginaccint.bin.o dummies.o +ginaccint_bin_LDADD = $(LDADD) +ginaccint_bin_DEPENDENCIES = +ginaccint_bin_LDFLAGS = +ginaccint_SOURCES = ginaccint.c +ginaccint_OBJECTS = ginaccint.o ginaccint_LDADD = $(LDADD) ginaccint_DEPENDENCIES = ginaccint_LDFLAGS = @@ -143,16 +149,17 @@ man1dir = $(mandir)/man1 MANS = $(man_MANS) NROFF = nroff -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = Makefile.am Makefile.in ginaccint.in DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP_ENV = --best -DEP_FILES = .deps/dummies.P .deps/ginaccint.P .deps/libginac.a.P -SOURCES = libginac.a.c $(ginaccint_SOURCES) -OBJECTS = libginac.a.o $(ginaccint_OBJECTS) +DEP_FILES = .deps/dummies.P .deps/ginaccint.P .deps/ginaccint.bin.P \ +.deps/libginac.la.P +SOURCES = libginac.la.c $(ginaccint_bin_SOURCES) ginaccint.c +OBJECTS = libginac.la.lo $(ginaccint_bin_OBJECTS) ginaccint.o all: all-redirect .SUFFIXES: @@ -164,15 +171,17 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status +ginaccint: $(top_builddir)/config.status ginaccint.in + cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status -mostlyclean-noinstLIBRARIES: +mostlyclean-noinstLTLIBRARIES: -clean-noinstLIBRARIES: - -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) -distclean-noinstLIBRARIES: +distclean-noinstLTLIBRARIES: -maintainer-clean-noinstLIBRARIES: +maintainer-clean-noinstLTLIBRARIES: .s.o: $(COMPILE) -c $< @@ -230,6 +239,10 @@ uninstall-binPROGRAMS: list='$(bin_PROGRAMS)'; for p in $$list; do \ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ done + +ginaccint: $(ginaccint_OBJECTS) $(ginaccint_DEPENDENCIES) + @rm -f ginaccint + $(LINK) $(ginaccint_LDFLAGS) $(ginaccint_OBJECTS) $(ginaccint_LDADD) $(LIBS) .cpp.o: $(CXXCOMPILE) -c $< .cpp.lo: @@ -316,7 +329,7 @@ distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ - cp -pr $$/$$file $(distdir)/$$file; \ + cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ @@ -393,7 +406,7 @@ install-am: all-am install: install-am uninstall-am: uninstall-binPROGRAMS uninstall-man uninstall: uninstall-am -all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(MANS) +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(MANS) all-redirect: all-am install-strip: $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install @@ -410,26 +423,26 @@ distclean-generic: -rm -f config.cache config.log stamp-h stamp-h[0-9]* maintainer-clean-generic: -mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ +mostlyclean-am: mostlyclean-noinstLTLIBRARIES mostlyclean-compile \ mostlyclean-libtool mostlyclean-binPROGRAMS \ mostlyclean-tags mostlyclean-depend mostlyclean-generic mostlyclean: mostlyclean-am -clean-am: clean-noinstLIBRARIES clean-compile clean-libtool \ +clean-am: clean-noinstLTLIBRARIES clean-compile clean-libtool \ clean-binPROGRAMS clean-tags clean-depend clean-generic \ mostlyclean-am clean: clean-am -distclean-am: distclean-noinstLIBRARIES distclean-compile \ +distclean-am: distclean-noinstLTLIBRARIES distclean-compile \ distclean-libtool distclean-binPROGRAMS distclean-tags \ distclean-depend distclean-generic clean-am -rm -f libtool distclean: distclean-am -maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ +maintainer-clean-am: maintainer-clean-noinstLTLIBRARIES \ maintainer-clean-compile maintainer-clean-libtool \ maintainer-clean-binPROGRAMS maintainer-clean-tags \ maintainer-clean-depend maintainer-clean-generic \ @@ -439,8 +452,8 @@ maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ maintainer-clean: maintainer-clean-am -.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ -clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +.PHONY: mostlyclean-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \ +clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \ mostlyclean-compile distclean-compile clean-compile \ maintainer-clean-compile mostlyclean-libtool distclean-libtool \ clean-libtool maintainer-clean-libtool mostlyclean-binPROGRAMS \ @@ -457,14 +470,14 @@ maintainer-clean-generic clean mostlyclean distclean maintainer-clean # Build a modified library in the ginac-subdir and put it into the cint-subdir: -libginac.a: +libginac.la: (cd ../ginac && \ $(MAKE) clean; \ $(MAKE) CXXFLAGS="$$CXXFLAGS -DNO_NAMESPACE_GINAC" && \ $(MAKE) install-libLTLIBRARIES prefix=`pwd`/../cint libdir=`pwd`/../cint && \ $(MAKE) clean) -ginaccint: libginac.a ginaccint.cpp +ginaccint.bin: libginac.la ginaccint.bin.cpp $(MAKE) -f Makefile.makecint # Files which are generated by perl scripts @@ -472,7 +485,12 @@ $(srcdir)/dummies.h $(srcdir)/dummies.cpp: $(srcdir)/dummies.pl cd $(srcdir) && perl dummies.pl # Force build of headers before compilation -$(srcdir)/ginaccint.cpp: $(srcdir)/dummies.h +$(srcdir)/ginaccint.bin.cpp: $(srcdir)/dummies.h + +# Force make clean to call Makecint's own Makefile +makecint_clean: + (if [ -f Makefile.makecint ]; then $(MAKE) -f Makefile.makecint clean; fi) +clean: makecint_clean # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/cint/ginaccint.1 b/cint/ginaccint.1 index c74405ae..0ce268b5 100644 --- a/cint/ginaccint.1 +++ b/cint/ginaccint.1 @@ -40,13 +40,29 @@ or a semicolon .RB ( ; ) is encountered. +.SS SPECIAL COMMANDS +.IP "\fB.cint\fR" +Switch to cint interactive mode. +.IP "\fB.function\fR" -.SS FUNCTION DEFINITIONS -GiNaC-cint must be put into a special mode in order to define a -function. This is done with the command -.RB .function . -After that any function definition in valid C++ syntax may be typed -in. It becomes immediatly available for usage. +Allow a function definition in interactive mode. GiNaC-cint must be +put into a special mode in order to define a function. After that any +function definition in valid C++ syntax may be typed in. It becomes +immediatly available for usage. + +.IP "\fBquit;\fR" +Exit from GiNaC-Cint. Same as +.BR "exit;" , +.BR "bye;" , +.BR ".q" , +.BR ".quit" , +.BR ".exit " or +.BR ".bye" . + +.IP "\fBOut\fP\fInum\fP" +Returns the expression whose output was marked +.BR "\fBOut\fP\fInum\fP" +as a handle. .SH EXAMPLES .nf @@ -55,20 +71,32 @@ GiNaC> ex a = pow(x,2)-x-2; GiNaC> ex b = pow(x+1,2); GiNaC> ex s = a/b; GiNaC> s.diff(x); -out1 -2*(1+x)^(-3)*(-2-x+x^2)+(-1+2*x)*(1+x)^(-2) +Out1 = -2*(1+x)^(-3)*(-2-x+x^2)+(-1+2*x)*(1+x)^(-2) GiNaC> s.normal(); -out2 (-2+x)*(1+x)^(-1) +Out2 = (-2+x)*(1+x)^(-1) +GiNaC> for (int i=2; i<20; i+=2) { + > cout << "B(" << i << ") == " << bernoulli(i) << endl; + > } +B(2)==1/6 +B(4)==-1/30 +B(6)==1/42 +B(8)==-1/30 +B(10)==5/66 +B(12)==-691/2730 +B(14)==7/6 +B(16)==-3617/510 +B(18)==43867/798 GiNaC> .function next expression can be a function definition GiNaC> ex EulerNumber(unsigned n) > { > symbol x; - > ex generator = pow(cosh(x),-1); + > const ex generator = pow(cosh(x),-1); > return generator.diff(x,n).subs(x==0); > } creating file /tmp/ginac26197caa GiNaC> EulerNumber(42); -out3 -10364622733519612119397957304745185976310201 +Out3 = -10364622733519612119397957304745185976310201 GiNaC> quit; .fi @@ -85,13 +113,17 @@ you encounter as far as possible and contact Masaharu Goto .SH AUTHOR .TP -The GiNaC Group: +The GiNaC Group .br Christian Bauer .br Alexander Frink .br Richard Kreckel +.TP +Agilent Technologies Japan +.br +Masaharu Goto .SH SEE ALSO GiNaC Tutorial \- An open framework for symbolic computation within the C++ programming language diff --git a/cint/ginaccint.cpp b/cint/ginaccint.bin.cpp similarity index 76% rename from cint/ginaccint.cpp rename to cint/ginaccint.bin.cpp index 724bffb3..52f3ef48 100644 --- a/cint/ginaccint.cpp +++ b/cint/ginaccint.bin.cpp @@ -4,7 +4,8 @@ #include #include #include -#include +#include "ginac/ginac.h" +#include "config.h" #include extern "C" G__value G__exec_tempfile G__P((char *file)); @@ -15,7 +16,7 @@ extern "C" void G__store_undo_position(void); #include template -string ToString(T const & t) +string ToString(const T & t) { char buf[256]; ostrstream(buf,sizeof(buf)) << t << ends; @@ -46,28 +47,28 @@ void sigterm_handler(int n) bool is_whitespace_char(char c) { - return ((c==' ')||(c=='\t')||(c=='\n')||(c=='\r')); + return ((c==' ') || (c=='\t') || (c=='\n') || (c=='\r')); } char first_non_whitespace_char(char const * s) { - int l=strlen(s); - int pos=0; + int l = strlen(s); + int pos = 0; while ((pos=0)&&is_whitespace_char(s[pos])) pos--; + int pos = strlen(s)-1; + while ((pos>=0) && is_whitespace_char(s[pos])) pos--; return s[pos]; } string strip_whitespace(string const & s) { string s2; - int l=s.length(); + int l = s.length(); for (int pos=0; pos0; --i) + // varfill += ' '; exec_tempfile("ex "+varname+"(*ex::last_created_or_assigned_bp);\n" +"LLLAST=LLAST;\n" +"LLAST=LAST;\n" +"LAST="+varname+";\n" - +"cout << \""+varname+" \" << "+varname+" << endl << endl;"); + +"cout << \""+varname+" = \" << "+varname+" << endl << endl;"); } else { cout << "warning: last_created_or_assigned_bp modified 0 or not evaluated or not dynallocated" << endl; } @@ -137,14 +141,13 @@ void process_tempfile(string const & command) void greeting(void) { - cout << "Welcome to GiNaC-cint V" << VERSION << endl; + cout << "Welcome to GiNaC-cint (" << PACKAGE << " V" << VERSION << ")" << endl; cout << "This software is provided \"as is\" without any warranty. Copyright of Cint is" << endl << "owned by Agilent Technologies Japan and Masaharu Goto. Registration is" << endl << " __, _______ requested, at this moment, for commercial use. Send e-mail to" << endl << " (__) * | . The registration is free." << endl - << " ._) i N a C | The GiNaC framework is Copyright by Johannes Gutenberg Univ." << endl + << " ._) i N a C | The GiNaC framework is Copyright by Johannes Gutenberg Univ.," << endl << "<-------------' Germany and licensed under the terms and conditions of the GPL." << endl << endl; - cout << "To quit, type 'quit;', 'exit;', 'bye;', '.q', '.quit', '.exit' or '.bye'" << endl; } int main(void) @@ -162,18 +165,18 @@ int main(void) exec_tempfile("#include \n"); exec_tempfile("ex LAST,LLAST,LLLAST;\n"); - bool quit=false; + bool quit = false; bool next_command_is_function=false; while (!quit) { strcpy(prompt,"GiNaC> "); - int open_braces=0; + int open_braces = 0; bool end_of_command=false; string command; while (!end_of_command) { - line=G__input(prompt); + line = G__input(prompt); int pos = 0; - bool double_quote=false; + bool double_quote=false; bool single_quote=false; while(line[pos]!='\0') { switch(line[pos]) { @@ -184,10 +187,10 @@ int main(void) if (!double_quote) single_quote = !single_quote; break; case '{': - if ((!single_quote)&&(!double_quote)) open_braces++; + if ((!single_quote) && (!double_quote)) open_braces++; break; case '}': - if ((!single_quote)&&(!double_quote)) open_braces--; + if ((!single_quote) && (!double_quote)) open_braces--; break; } pos++; @@ -212,7 +215,7 @@ int main(void) (stripped_command==".quit")|| (stripped_command==".exit")|| (stripped_command==".bye")) { - quit=true; + quit = true; } else if (stripped_command==".function") { cout << "next expression can be a function definition" << endl; next_command_is_function=true; @@ -224,9 +227,9 @@ int main(void) } else if (command[0]=='.') { cout << "special command (TBD): " << command << endl; } else { - // cout << "now processing: " << command << endl; + // cout << "now processing: " << command << endl; if (next_command_is_function) { - next_command_is_function=false; + next_command_is_function = false; filenames.push_back(process_permanentfile(command)); } else { process_tempfile(command); diff --git a/cint/ginaccint.in b/cint/ginaccint.in new file mode 100644 index 00000000..2128a141 --- /dev/null +++ b/cint/ginaccint.in @@ -0,0 +1,13 @@ +#! /bin/sh + +binprog=`basename $0`".bin" +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +config_cintsysdir=@CINTSYSDIR@ + +if [ "x$CINTSYSDIR" = "x" ]; then + CINTSYSDIR=$config_cintsysdir + export CINTSYSDIR +fi +exec ${bindir}/${binprog} diff --git a/configure b/configure index fe76b789..4876d446 100755 --- a/configure +++ b/configure @@ -2942,10 +2942,10 @@ fi if [ "$CINT" -a "$MAKECINT" ]; then echo "$ac_t""creating cint/Makefile" 1>&6 (cd cint && \ - $MAKECINT -mk Makefile.makecint -o ginaccint -m \ + $MAKECINT -mk Makefile.makecint -o ginaccint.bin -m \ -D OBSCURE_CINT_HACK -D NO_NAMESPACE_GINAC \ -I .. -I $CINTSYSDIR -m -H ../ginac/ginac.h dummies.h \ - -C++ dummies.cpp -C++ ginaccint.cpp \ + -C++ dummies.cpp -C++ ginaccint.bin.cpp \ -l ./libginac.a -lcln -cint -M0x10; \ cd ..) LIBGINACCINT="libginac.a" @@ -2957,6 +2957,7 @@ fi + trap '' 1 2 15 cat > confcache <<\EOF # This file is a shell script that caches the results of configure @@ -3070,6 +3071,7 @@ doc/Makefile doc/tutorial/Makefile doc/reference/Makefile cint/Makefile +cint/ginaccint config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF @@ -3390,7 +3394,7 @@ cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h -chmod +x ginac-config +chmod +x ginac-config cint/ginaccint exit 0 EOF chmod +x $CONFIG_STATUS diff --git a/configure.in b/configure.in index 9249f9da..e962725c 100644 --- a/configure.in +++ b/configure.in @@ -163,10 +163,10 @@ if [[ "x$with_cint" != "xno" ]]; then if [[ "$CINT" -a "$MAKECINT" ]]; then AC_MSG_RESULT([creating cint/Makefile]) (cd cint && \ - $MAKECINT -mk Makefile.makecint -o ginaccint -m \ + $MAKECINT -mk Makefile.makecint -o ginaccint.bin -m \ -D OBSCURE_CINT_HACK -D NO_NAMESPACE_GINAC \ -I .. -I $CINTSYSDIR -m -H ../ginac/ginac.h dummies.h \ - -C++ dummies.cpp -C++ ginaccint.cpp \ + -C++ dummies.cpp -C++ ginaccint.bin.cpp \ -l ./libginac.a -lcln -cint -M0x10; \ cd ..) LIBGINACCINT="libginac.a" @@ -175,6 +175,7 @@ if [[ "x$with_cint" != "xno" ]]; then AC_MSG_ERROR([Cannot configure GiNaC-cint]) fi fi +AC_SUBST(CINTSYSDIR) AC_SUBST(LIBGINACCINT) AC_SUBST(GINACCINTDIR) @@ -191,5 +192,6 @@ doc/Makefile doc/tutorial/Makefile doc/reference/Makefile cint/Makefile -], [chmod +x ginac-config]) +cint/ginaccint +], [chmod +x ginac-config cint/ginaccint]) echo "Configuration done. Now type \"make\"." diff --git a/doc/Makefile.in b/doc/Makefile.in index e2011169..6fa6eccb 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -64,6 +64,7 @@ ARCHIVE_VERSION = @ARCHIVE_VERSION@ AS = @AS@ CC = @CC@ CINT = @CINT@ +CINTSYSDIR = @CINTSYSDIR@ CXX = @CXX@ CXXCPP = @CXXCPP@ DLLTOOL = @DLLTOOL@ @@ -273,7 +274,7 @@ distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ - cp -pr $$/$$file $(distdir)/$$file; \ + cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ diff --git a/doc/reference/Makefile.in b/doc/reference/Makefile.in index 47c0ee48..d9e81555 100644 --- a/doc/reference/Makefile.in +++ b/doc/reference/Makefile.in @@ -67,6 +67,7 @@ ARCHIVE_VERSION = @ARCHIVE_VERSION@ AS = @AS@ CC = @CC@ CINT = @CINT@ +CINTSYSDIR = @CINTSYSDIR@ CXX = @CXX@ CXXCPP = @CXXCPP@ DLLTOOL = @DLLTOOL@ @@ -169,7 +170,7 @@ distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ - cp -pr $$/$$file $(distdir)/$$file; \ + cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ diff --git a/doc/tutorial/Makefile.in b/doc/tutorial/Makefile.in index dcde4376..16fc4f93 100644 --- a/doc/tutorial/Makefile.in +++ b/doc/tutorial/Makefile.in @@ -66,6 +66,7 @@ ARCHIVE_VERSION = @ARCHIVE_VERSION@ AS = @AS@ CC = @CC@ CINT = @CINT@ +CINTSYSDIR = @CINTSYSDIR@ CXX = @CXX@ CXXCPP = @CXXCPP@ DLLTOOL = @DLLTOOL@ @@ -326,7 +327,7 @@ distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ - cp -pr $$/$$file $(distdir)/$$file; \ + cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi index 04b8908d..4cbf739d 100644 --- a/doc/tutorial/ginac.texi +++ b/doc/tutorial/ginac.texi @@ -215,11 +215,11 @@ generates Hermite polynomials in a specified free variable. #include using namespace GiNaC; -ex HermitePoly(symbol x, int deg) +ex HermitePoly(const symbol & x, int n) @{ - 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); + 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, n) * diff(HKer, x, n) / HKer); @} int main() @@ -422,19 +422,21 @@ installation. @c node-name, next, previous, up @section Prerequisites -In order to install GiNaC on your system, some prerequisites need -to be met. First of all, you need to have a C++-compiler adhering to -the ANSI-standard @cite{ISO/IEC 14882:1998(E)}. We used @acronym{GCC} for +In order to install GiNaC on your system, some prerequisites need to be +met. First of all, you need to have a C++-compiler adhering to the +ANSI-standard @cite{ISO/IEC 14882:1998(E)}. We used @acronym{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 @file{/bin/sh}, GNU @command{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 -@acronym{CLN} is extensively used and needs to be installed on your system. -Please get it from @uref{ftp://ftp.santafe.edu/pub/gnu/} or from -@uref{ftp://ftp.ilog.fr/pub/Users/haible/gnu/, Bruno Haible's FTP site} -(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 +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 @acronym{CLN} is extensively used and needs to be +installed on your system. Please get it either from +@uref{ftp://ftp.santafe.edu/pub/gnu/}, from +@uref{ftp://ftpthep.physik.uni-mainz.de/pub/gnu/, GiNaC's FTP site} or +from @uref{ftp://ftp.ilog.fr/pub/Users/haible/gnu/, Bruno Haible's FTP +site} (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. @@ -1536,7 +1538,7 @@ using namespace GiNaC; ex EulerNumber(unsigned n) @{ symbol x; - ex generator = pow(cosh(x),-1); + const ex generator = pow(cosh(x),-1); return generator.diff(x,n).subs(x==0); @} diff --git a/ginac/Makefile.am b/ginac/Makefile.am index 27123093..e0cf87d5 100644 --- a/ginac/Makefile.am +++ b/ginac/Makefile.am @@ -1,8 +1,8 @@ ## Process this file with automake to produce Makefile.in lib_LTLIBRARIES = libginac.la -libginac_la_SOURCES = add.cpp archive.cpp basic.cpp constant.cpp diff.cpp \ - ex.cpp expairseq.cpp exprseq.cpp fail.cpp function.cpp inifcns.cpp \ +libginac_la_SOURCES = add.cpp archive.cpp basic.cpp constant.cpp ex.cpp \ + expairseq.cpp exprseq.cpp fail.cpp function.cpp inifcns.cpp \ inifcns_trans.cpp inifcns_zeta.cpp inifcns_gamma.cpp matrix.cpp mul.cpp \ normal.cpp numeric.cpp operators.cpp power.cpp registrar.cpp relational.cpp \ symbol.cpp pseries.cpp utils.cpp ncmul.cpp clifford.cpp structure.cpp \ diff --git a/ginac/Makefile.in b/ginac/Makefile.in index 7fa0a4e1..e9eff67c 100644 --- a/ginac/Makefile.in +++ b/ginac/Makefile.in @@ -64,6 +64,7 @@ ARCHIVE_VERSION = @ARCHIVE_VERSION@ AS = @AS@ CC = @CC@ CINT = @CINT@ +CINTSYSDIR = @CINTSYSDIR@ CXX = @CXX@ CXXCPP = @CXXCPP@ DLLTOOL = @DLLTOOL@ @@ -104,7 +105,7 @@ VERSION = @VERSION@ YACC = @YACC@ lib_LTLIBRARIES = libginac.la -libginac_la_SOURCES = add.cpp archive.cpp basic.cpp constant.cpp diff.cpp ex.cpp expairseq.cpp exprseq.cpp fail.cpp function.cpp inifcns.cpp inifcns_trans.cpp inifcns_zeta.cpp inifcns_gamma.cpp matrix.cpp mul.cpp normal.cpp numeric.cpp operators.cpp power.cpp registrar.cpp relational.cpp symbol.cpp pseries.cpp utils.cpp ncmul.cpp clifford.cpp structure.cpp color.cpp indexed.cpp idx.cpp isospin.cpp exprseq_suppl.cpp lst.cpp lst_suppl.cpp simp_lor.cpp coloridx.cpp lorentzidx.cpp lortensor.cpp debugmsg.h utils.h +libginac_la_SOURCES = add.cpp archive.cpp basic.cpp constant.cpp ex.cpp expairseq.cpp exprseq.cpp fail.cpp function.cpp inifcns.cpp inifcns_trans.cpp inifcns_zeta.cpp inifcns_gamma.cpp matrix.cpp mul.cpp normal.cpp numeric.cpp operators.cpp power.cpp registrar.cpp relational.cpp symbol.cpp pseries.cpp utils.cpp ncmul.cpp clifford.cpp structure.cpp color.cpp indexed.cpp idx.cpp isospin.cpp exprseq_suppl.cpp lst.cpp lst_suppl.cpp simp_lor.cpp coloridx.cpp lorentzidx.cpp lortensor.cpp debugmsg.h utils.h libginac_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) -release $(LT_RELEASE) @@ -123,13 +124,13 @@ CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ libginac_la_LIBADD = -libginac_la_OBJECTS = add.lo archive.lo basic.lo constant.lo diff.lo \ -ex.lo expairseq.lo exprseq.lo fail.lo function.lo inifcns.lo \ -inifcns_trans.lo inifcns_zeta.lo inifcns_gamma.lo matrix.lo mul.lo \ -normal.lo numeric.lo operators.lo power.lo registrar.lo relational.lo \ -symbol.lo pseries.lo utils.lo ncmul.lo clifford.lo structure.lo \ -color.lo indexed.lo idx.lo isospin.lo exprseq_suppl.lo lst.lo \ -lst_suppl.lo simp_lor.lo coloridx.lo lorentzidx.lo lortensor.lo +libginac_la_OBJECTS = add.lo archive.lo basic.lo constant.lo ex.lo \ +expairseq.lo exprseq.lo fail.lo function.lo inifcns.lo inifcns_trans.lo \ +inifcns_zeta.lo inifcns_gamma.lo matrix.lo mul.lo normal.lo numeric.lo \ +operators.lo power.lo registrar.lo relational.lo symbol.lo pseries.lo \ +utils.lo ncmul.lo clifford.lo structure.lo color.lo indexed.lo idx.lo \ +isospin.lo exprseq_suppl.lo lst.lo lst_suppl.lo simp_lor.lo coloridx.lo \ +lorentzidx.lo lortensor.lo 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) @@ -150,7 +151,7 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = tar GZIP_ENV = --best DEP_FILES = .deps/add.P .deps/archive.P .deps/basic.P .deps/clifford.P \ -.deps/color.P .deps/coloridx.P .deps/constant.P .deps/diff.P .deps/ex.P \ +.deps/color.P .deps/coloridx.P .deps/constant.P .deps/ex.P \ .deps/expairseq.P .deps/exprseq.P .deps/exprseq_suppl.P .deps/fail.P \ .deps/function.P .deps/idx.P .deps/indexed.P .deps/inifcns.P \ .deps/inifcns_gamma.P .deps/inifcns_trans.P .deps/inifcns_zeta.P \ @@ -294,7 +295,7 @@ distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ - cp -pr $$/$$file $(distdir)/$$file; \ + cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ diff --git a/ginac/add.cpp b/ginac/add.cpp index 86703ddc..5db2045c 100644 --- a/ginac/add.cpp +++ b/ginac/add.cpp @@ -414,6 +414,14 @@ ex add::simplify_ncmul(const exvector & v) const // protected +/** Implementation of ex::diff() for a sum. It differentiates each term. + * @see ex::diff */ +ex add::derivative(const symbol & s) const +{ + // D(a+b+c)=D(a)+D(b)+D(c) + return (new add(diffchildren(s)))->setflag(status_flags::dynallocated); +} + int add::compare_same_type(const basic & other) const { return inherited::compare_same_type(other); diff --git a/ginac/add.h b/ginac/add.h index 176663fb..4e5ec2bb 100644 --- a/ginac/add.h +++ b/ginac/add.h @@ -70,7 +70,6 @@ public: int ldegree(const symbol & s) const; ex coeff(const symbol & s, int n=1) const; ex eval(int level=0) const; - ex diff(const symbol & s) const; ex series(const symbol & s, const ex & point, int order) const; ex normal(lst &sym_lst, lst &repl_lst, int level=0) const; numeric integer_content(void) const; @@ -79,6 +78,7 @@ public: exvector get_indices(void) const; ex simplify_ncmul(const exvector & v) const; protected: + ex derivative(const symbol & s) const; int compare_same_type(const basic & other) const; bool is_equal_same_type(const basic & other) const; unsigned return_type(void) const; diff --git a/ginac/basic.cpp b/ginac/basic.cpp index e2a9320e..43dbf336 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -293,6 +293,27 @@ ex basic::subs(const lst & ls, const lst & lr) const return *this; } +/** Default interface of nth derivative ex::diff(s, n). It should be called + * instead of ::derivative(s) for first derivatives and for nth derivatives it + * just recurses down. + * + * @param s symbol to differentiate in + * @param nth order of differentiation + * @see ex::diff */ +ex basic::diff(const symbol & s, unsigned nth) const +{ + // FIXME: Check if it is evaluated! + if (!nth) + return ex(*this); + ex ndiff = derivative(s); + while (!ndiff.is_zero() && // stop differentiating zeroes + nth>1) { + ndiff = ndiff.diff(s); + --nth; + } + return ndiff; +} + exvector basic::get_indices(void) const { return exvector(); // return an empty exvector @@ -305,6 +326,15 @@ ex basic::simplify_ncmul(const exvector & v) const // protected +/** Default implementation of ex::diff(). It simply throws an error message. + * + * @exception logic_error (differentiation not supported by this type) + * @see ex::diff */ +ex basic::derivative(const symbol & s) const +{ + throw(std::logic_error("differentiation not supported by this type")); +} + int basic::compare_same_type(const basic & other) const { return compare_pointers(this, &other); @@ -349,6 +379,7 @@ ex basic::expand(unsigned options) const return this->setflag(status_flags::expanded); } + ////////// // non-virtual functions in this class ////////// diff --git a/ginac/basic.h b/ginac/basic.h index ebe10e68..4e9b5171 100644 --- a/ginac/basic.h +++ b/ginac/basic.h @@ -137,7 +137,6 @@ public: // only const functions please (may break reference counting) virtual ex collect(const symbol & s) const; virtual ex eval(int level=0) const; virtual ex evalf(int level=0) const; - virtual ex diff(const symbol & s) const; virtual ex series(const symbol & s, const ex & point, int order) const; virtual ex subs(const lst & ls, const lst & lr) const; virtual ex normal(lst &sym_lst, lst &repl_lst, int level=0) const; @@ -147,6 +146,7 @@ public: // only const functions please (may break reference counting) virtual exvector get_indices(void) const; virtual ex simplify_ncmul(const exvector & v) const; protected: // non-const functions should be called from class ex only + virtual ex derivative(const symbol & s) const; virtual int compare_same_type(const basic & other) const; virtual bool is_equal_same_type(const basic & other) const; virtual unsigned return_type(void) const; @@ -157,6 +157,7 @@ protected: // non-const functions should be called from class ex only // non-virtual functions in this class public: ex subs(const ex & e) const; + ex diff(const symbol & s, unsigned nth=1) const; int compare(const basic & other) const; bool is_equal(const basic & other) const; const basic & hold(void) const; diff --git a/ginac/constant.cpp b/ginac/constant.cpp index cbf90308..b8543092 100644 --- a/ginac/constant.cpp +++ b/ginac/constant.cpp @@ -191,6 +191,14 @@ ex constant::evalf(int level) const // protected +/** Implementation of ex::diff() for a constant. It always returns 0. + * + * @see ex::diff */ +ex constant::derivative(const symbol & s) const +{ + return _ex0(); +} + int constant::compare_same_type(const basic & other) const { GINAC_ASSERT(is_exactly_of_type(other, constant)); diff --git a/ginac/constant.h b/ginac/constant.h index c29ecf01..91ede282 100644 --- a/ginac/constant.h +++ b/ginac/constant.h @@ -65,8 +65,8 @@ public: void printtree(ostream & os, unsigned indent) const; void printcsrc(ostream & os, unsigned type, unsigned upper_precedence=0) const; ex evalf(int level=0) const; - ex diff(const symbol & s) const; protected: + ex derivative(const symbol & s) const; int compare_same_type(const basic & other) const; bool is_equal_same_type(const basic & other) const; diff --git a/ginac/container.pl b/ginac/container.pl index a66df7b9..3a7f9bd8 100755 --- a/ginac/container.pl +++ b/ginac/container.pl @@ -189,7 +189,7 @@ public: ex eval(int level=0) const; ex evalf(int level=0) const; ex normal(lst &sym_lst, lst &repl_lst, int level=0) const; - ex diff(const symbol & s) const; + ex derivative(const symbol & s) const; ex subs(const lst & ls, const lst & lr) const; protected: int compare_same_type(const basic & other) const; @@ -634,7 +634,7 @@ ex ${CONTAINER}::normal(lst &sym_lst, lst &repl_lst, int level) const return n.bp->basic::normal(sym_lst,repl_lst,level); } -ex ${CONTAINER}::diff(const symbol & s) const +ex ${CONTAINER}::derivative(const symbol & s) const { return this${CONTAINER}(diffchildren(s)); } diff --git a/ginac/diff.cpp b/ginac/diff.cpp deleted file mode 100644 index 4b6e9c83..00000000 --- a/ginac/diff.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/** @file diff.cpp - * - * Implementation of symbolic differentiation in all of GiNaC's classes. */ - -/* - * 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 "basic.h" -#include "ex.h" -#include "add.h" -#include "constant.h" -#include "expairseq.h" -#include "indexed.h" -#include "inifcns.h" -#include "mul.h" -#include "ncmul.h" -#include "numeric.h" -#include "power.h" -#include "relational.h" -#include "pseries.h" -#include "symbol.h" -#include "utils.h" - -#ifndef NO_NAMESPACE_GINAC -namespace GiNaC { -#endif // ndef NO_NAMESPACE_GINAC - -/** Default implementation of ex::diff(). It prints and error message and returns a fail object. - * @see ex::diff */ -ex basic::diff(const symbol & s) const -{ - throw(std::logic_error("differentiation not supported by this type")); -} - - -/** Implementation of ex::diff() for a numeric. It always returns 0. - * - * @see ex::diff */ -ex numeric::diff(const symbol & s) const -{ - return _ex0(); -} - - -/** Implementation of ex::diff() for single differentiation of a symbol. - * It returns 1 or 0. - * - * @see ex::diff */ -ex symbol::diff(const symbol & s) const -{ - if (compare_same_type(s)) { - return _ex0(); - } else { - return _ex1(); - } -} - -/** Implementation of ex::diff() for a constant. It always returns 0. - * - * @see ex::diff */ -ex constant::diff(const symbol & s) const -{ - return _ex0(); -} - -/** Implementation of ex::diff() for multiple differentiation of a symbol. - * It returns the symbol, 1 or 0. - * - * @param nth order of differentiation - * @see ex::diff */ -ex symbol::diff(const symbol & s, unsigned nth) const -{ - if (compare_same_type(s)) { - switch (nth) { - case 0: - return s; - break; - case 1: - return _ex1(); - break; - default: - return _ex0(); - } - } else { - return _ex1(); - } -} - - -/** Implementation of ex::diff() for an indexed object. It always returns 0. - * @see ex::diff */ -ex indexed::diff(const symbol & s) const -{ - return _ex0(); -} - - -/** Implementation of ex::diff() for an expairseq. It differentiates all elements of the sequence. - * @see ex::diff */ -ex expairseq::diff(const symbol & s) const -{ - return thisexpairseq(diffchildren(s),overall_coeff); -} - - -/** Implementation of ex::diff() for a sum. It differentiates each term. - * @see ex::diff */ -ex add::diff(const symbol & s) const -{ - // D(a+b+c)=D(a)+D(b)+D(c) - return (new add(diffchildren(s)))->setflag(status_flags::dynallocated); -} - - -/** Implementation of ex::diff() for a product. It applies the product rule. - * @see ex::diff */ -ex mul::diff(const symbol & s) const -{ - exvector new_seq; - new_seq.reserve(seq.size()); - - // D(a*b*c)=D(a)*b*c+a*D(b)*c+a*b*D(c) - for (unsigned i=0; i!=seq.size(); i++) { - epvector sub_seq=seq; - sub_seq[i] = split_ex_to_pair(sub_seq[i].coeff* - power(sub_seq[i].rest,sub_seq[i].coeff-1)* - sub_seq[i].rest.diff(s)); - new_seq.push_back((new mul(sub_seq,overall_coeff))->setflag(status_flags::dynallocated)); - } - return (new add(new_seq))->setflag(status_flags::dynallocated); -} - - -/** Implementation of ex::diff() for a non-commutative product. It always returns 0. - * @see ex::diff */ -ex ncmul::diff(const symbol & s) const -{ - return _ex0(); -} - - -/** Implementation of ex::diff() for a power. - * @see ex::diff */ -ex power::diff(const symbol & s) const -{ - if (exponent.info(info_flags::real)) { - // D(b^r) = r * b^(r-1) * D(b) (faster than the formula below) - return mul(mul(exponent, power(basis, exponent - _ex1())), basis.diff(s)); - } else { - // D(b^e) = b^e * (D(e)*ln(b) + e*D(b)/b) - return mul(power(basis, exponent), - add(mul(exponent.diff(s), log(basis)), - mul(mul(exponent, basis.diff(s)), power(basis, -1)))); - } -} - - -/** Implementation of ex::diff() for functions. It applies the chain rule, - * except for the Order term function. - * @see ex::diff */ -ex function::diff(const symbol & s) const -{ - exvector new_seq; - - if (serial==function_index_Order) { - // Order Term function only differentiates the argument - return Order(seq[0].diff(s)); - } else { - // Chain rule - ex arg_diff; - for (unsigned i=0; i!=seq.size(); i++) { - arg_diff = seq[i].diff(s); - // We apply the chain rule only when it makes sense. This is not - // just for performance reasons but also to allow functions to - // throw when differentiated with respect to one of its arguments - // without running into trouble with our automatic full - // differentiation: - if (!arg_diff.is_zero()) - new_seq.push_back(mul(pdiff(i), arg_diff)); - } - } - return add(new_seq); -} - - -/** Implementation of ex::diff() for a power series. It treats the series as a polynomial. - * @see ex::diff */ -ex pseries::diff(const symbol & s) const -{ - if (s == var) { - epvector new_seq; - epvector::const_iterator it = seq.begin(), itend = seq.end(); - - // FIXME: coeff might depend on var - while (it != itend) { - if (is_order_function(it->rest)) { - new_seq.push_back(expair(it->rest, it->coeff - 1)); - } else { - ex c = it->rest * it->coeff; - if (!c.is_zero()) - new_seq.push_back(expair(c, it->coeff - 1)); - } - it++; - } - return pseries(var, point, new_seq); - } else { - return *this; - } -} - - -/** Compute partial derivative of an expression. - * - * @param s symbol by which the expression is derived - * @param nth order of derivative (default 1) - * @return partial derivative as a new expression */ - -ex ex::diff(const symbol & s, unsigned nth) const -{ - GINAC_ASSERT(bp!=0); - - if (nth==0) { - return *this; - } - - ex ndiff = bp->diff(s); - while (nth>1) { - ndiff = ndiff.diff(s); - --nth; - } - return ndiff; -} - -#ifndef NO_NAMESPACE_GINAC -} // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC diff --git a/ginac/ex.cpp b/ginac/ex.cpp index 78991125..a390d714 100644 --- a/ginac/ex.cpp +++ b/ginac/ex.cpp @@ -374,6 +374,21 @@ ex ex::evalf(int level) const return bp->evalf(level); } +/** Compute partial derivative of an expression. + * + * @param s symbol by which the expression is derived + * @param nth order of derivative (default 1) + * @return partial derivative as a new expression */ +ex ex::diff(const symbol & s, unsigned nth) const +{ + GINAC_ASSERT(bp!=0); + + if (!nth) + return *this; + else + return bp->diff(s, nth); +} + ex ex::subs(const lst & ls, const lst & lr) const { GINAC_ASSERT(bp!=0); diff --git a/ginac/expairseq.cpp b/ginac/expairseq.cpp index be065ce6..fe910d03 100644 --- a/ginac/expairseq.cpp +++ b/ginac/expairseq.cpp @@ -372,6 +372,14 @@ ex expairseq::subs(const lst & ls, const lst & lr) const // protected +/** Implementation of ex::diff() for an expairseq. It differentiates all elements of the + * sequence. + * @see ex::diff */ +ex expairseq::derivative(const symbol & s) const +{ + return thisexpairseq(diffchildren(s),overall_coeff); +} + int expairseq::compare_same_type(const basic & other) const { GINAC_ASSERT(is_of_type(other, expairseq)); diff --git a/ginac/expairseq.h b/ginac/expairseq.h index 54062f64..9c32dbdf 100644 --- a/ginac/expairseq.h +++ b/ginac/expairseq.h @@ -102,9 +102,9 @@ public: ex eval(int level=0) const; ex evalf(int level=0) const; ex normal(lst &sym_lst, lst &repl_lst, int level=0) const; - ex diff(const symbol & s) const; ex subs(const lst & ls, const lst & lr) const; protected: + ex derivative(const symbol & s) const; int compare_same_type(const basic & other) const; bool is_equal_same_type(const basic & other) const; unsigned return_type(void) const; diff --git a/ginac/function.pl b/ginac/function.pl index 8ad1abe5..b7e14023 100755 --- a/ginac/function.pl +++ b/ginac/function.pl @@ -296,11 +296,11 @@ public: ex expand(unsigned options=0) const; ex eval(int level=0) const; ex evalf(int level=0) const; - ex diff(const symbol & s) const; ex series(const symbol & s, const ex & point, int order) const; ex thisexprseq(const exvector & v) const; ex thisexprseq(exvector * vp) const; protected: + ex derivative(const symbol & s) const; int compare_same_type(const basic & other) const; bool is_equal_same_type(const basic & other) const; unsigned return_type(void) const; @@ -311,7 +311,7 @@ protected: // non-virtual functions in this class protected: - ex pdiff(unsigned diff_param) const; // partial differentiation + ex pderivative(unsigned diff_param) const; // partial differentiation static vector & registered_functions(void); public: // the following lines have been generated for max. ${maxargs} parameters @@ -385,6 +385,7 @@ $implementation=< & function::registered_functions(void) diff --git a/ginac/indexed.cpp b/ginac/indexed.cpp index 1f67038f..0f6726e5 100644 --- a/ginac/indexed.cpp +++ b/ginac/indexed.cpp @@ -221,6 +221,13 @@ exvector indexed::get_indices(void) const // protected +/** Implementation of ex::diff() for an indexed object. It always returns 0. + * @see ex::diff */ +ex indexed::derivative(const symbol & s) const +{ + return _ex0(); +} + int indexed::compare_same_type(const basic & other) const { GINAC_ASSERT(is_of_type(other,indexed)); diff --git a/ginac/indexed.h b/ginac/indexed.h index 5988f0a0..919fc18e 100644 --- a/ginac/indexed.h +++ b/ginac/indexed.h @@ -64,9 +64,9 @@ public: void print(ostream & os, unsigned upper_precedence=0) const; void printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const; bool info(unsigned inf) const; - ex diff(const symbol & s) const; exvector get_indices(void) const; protected: + ex derivative(const symbol & s) const; int compare_same_type(const basic & other) const; bool is_equal_same_type(const basic & other) const; unsigned return_type(void) const; diff --git a/ginac/inifcns_gamma.cpp b/ginac/inifcns_gamma.cpp index 503c44c8..9e96fda8 100644 --- a/ginac/inifcns_gamma.cpp +++ b/ginac/inifcns_gamma.cpp @@ -94,9 +94,9 @@ static ex gamma_eval(const ex & x) } -static ex gamma_diff(const ex & x, unsigned diff_param) +static ex gamma_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx log(gamma(x)) -> psi(x) // d/dx gamma(x) -> psi(x)*gamma(x) @@ -126,7 +126,7 @@ static ex gamma_series(const ex & x, const symbol & s, const ex & pt, int order) } -REGISTER_FUNCTION(gamma, gamma_eval, gamma_evalf, gamma_diff, gamma_series); +REGISTER_FUNCTION(gamma, gamma_eval, gamma_evalf, gamma_deriv, gamma_series); ////////// @@ -181,16 +181,16 @@ static ex beta_eval(const ex & x, const ex & y) } -static ex beta_diff(const ex & x, const ex & y, unsigned diff_param) +static ex beta_deriv(const ex & x, const ex & y, unsigned deriv_param) { - GINAC_ASSERT(diff_param<2); + GINAC_ASSERT(deriv_param<2); ex retval; // d/dx beta(x,y) -> (psi(x)-psi(x+y)) * beta(x,y) - if (diff_param==0) + if (deriv_param==0) retval = (psi(x)-psi(x+y))*beta(x,y); // d/dy beta(x,y) -> (psi(y)-psi(x+y)) * beta(x,y) - if (diff_param==1) + if (deriv_param==1) retval = (psi(y)-psi(x+y))*beta(x,y); return retval; } @@ -229,7 +229,7 @@ static ex beta_series(const ex & x, const ex & y, const symbol & s, const ex & p } -REGISTER_FUNCTION(beta, beta_eval, beta_evalf, beta_diff, beta_series); +REGISTER_FUNCTION(beta, beta_eval, beta_evalf, beta_deriv, beta_series); ////////// @@ -290,9 +290,9 @@ static ex psi1_eval(const ex & x) return psi(x).hold(); } -static ex psi1_diff(const ex & x, unsigned diff_param) +static ex psi1_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx psi(x) -> psi(1,x) return psi(_ex1(), x); @@ -319,7 +319,7 @@ static ex psi1_series(const ex & x, const symbol & s, const ex & pt, int order) return (psi(x+m+_ex1())-recur).series(s, pt, order); } -const unsigned function_index_psi1 = function::register_new("psi", psi1_eval, psi1_evalf, psi1_diff, psi1_series); +const unsigned function_index_psi1 = function::register_new("psi", psi1_eval, psi1_evalf, psi1_deriv, psi1_series); ////////// // Psi-functions (aka polygamma-functions) psi(0,x)==psi(x) @@ -400,11 +400,11 @@ static ex psi2_eval(const ex & n, const ex & x) return psi(n, x).hold(); } -static ex psi2_diff(const ex & n, const ex & x, unsigned diff_param) +static ex psi2_deriv(const ex & n, const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param<2); + GINAC_ASSERT(deriv_param<2); - if (diff_param==0) { + if (deriv_param==0) { // d/dn psi(n,x) throw(std::logic_error("cannot diff psi(n,x) with respect to n")); } @@ -435,7 +435,7 @@ static ex psi2_series(const ex & n, const ex & x, const symbol & s, const ex & p return (psi(n, x+m+_ex1())-recur).series(s, pt, order); } -const unsigned function_index_psi2 = function::register_new("psi", psi2_eval, psi2_evalf, psi2_diff, psi2_series); +const unsigned function_index_psi2 = function::register_new("psi", psi2_eval, psi2_evalf, psi2_deriv, psi2_series); #ifndef NO_NAMESPACE_GINAC } // namespace GiNaC diff --git a/ginac/inifcns_trans.cpp b/ginac/inifcns_trans.cpp index da763b40..e0d0999b 100644 --- a/ginac/inifcns_trans.cpp +++ b/ginac/inifcns_trans.cpp @@ -80,15 +80,15 @@ static ex exp_eval(const ex & x) return exp(x).hold(); } -static ex exp_diff(const ex & x, unsigned diff_param) +static ex exp_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx exp(x) -> exp(x) return exp(x); } -REGISTER_FUNCTION(exp, exp_eval, exp_evalf, exp_diff, NULL); +REGISTER_FUNCTION(exp, exp_eval, exp_evalf, exp_deriv, NULL); ////////// // natural logarithm @@ -133,15 +133,15 @@ static ex log_eval(const ex & x) return log(x).hold(); } -static ex log_diff(const ex & x, unsigned diff_param) +static ex log_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx log(x) -> 1/x return power(x, _ex_1()); } -REGISTER_FUNCTION(log, log_eval, log_evalf, log_diff, NULL); +REGISTER_FUNCTION(log, log_eval, log_evalf, log_deriv, NULL); ////////// // sine (trigonometric function) @@ -212,15 +212,15 @@ static ex sin_eval(const ex & x) return sin(x).hold(); } -static ex sin_diff(const ex & x, unsigned diff_param) +static ex sin_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx sin(x) -> cos(x) return cos(x); } -REGISTER_FUNCTION(sin, sin_eval, sin_evalf, sin_diff, NULL); +REGISTER_FUNCTION(sin, sin_eval, sin_evalf, sin_deriv, NULL); ////////// // cosine (trigonometric function) @@ -291,15 +291,15 @@ static ex cos_eval(const ex & x) return cos(x).hold(); } -static ex cos_diff(const ex & x, unsigned diff_param) +static ex cos_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx cos(x) -> -sin(x) return _ex_1()*sin(x); } -REGISTER_FUNCTION(cos, cos_eval, cos_evalf, cos_diff, NULL); +REGISTER_FUNCTION(cos, cos_eval, cos_evalf, cos_deriv, NULL); ////////// // tangent (trigonometric function) @@ -367,9 +367,9 @@ static ex tan_eval(const ex & x) return tan(x).hold(); } -static ex tan_diff(const ex & x, unsigned diff_param) +static ex tan_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx tan(x) -> 1+tan(x)^2; return (_ex1()+power(tan(x),_ex2())); @@ -378,7 +378,7 @@ static ex tan_diff(const ex & x, unsigned diff_param) static ex tan_series(const ex & x, const symbol & s, const ex & pt, int order) { // method: - // Taylor series where there is no pole falls back to tan_diff. + // Taylor series where there is no pole falls back to tan_deriv. // On a pole simply expand sin(x)/cos(x). const ex x_pt = x.subs(s==pt); if (!(2*x_pt/Pi).info(info_flags::odd)) @@ -387,7 +387,7 @@ static ex tan_series(const ex & x, const symbol & s, const ex & pt, int order) return (sin(x)/cos(x)).series(s, pt, order+2); } -REGISTER_FUNCTION(tan, tan_eval, tan_evalf, tan_diff, tan_series); +REGISTER_FUNCTION(tan, tan_eval, tan_evalf, tan_deriv, tan_series); ////////// // inverse sine (arc sine) @@ -428,15 +428,15 @@ static ex asin_eval(const ex & x) return asin(x).hold(); } -static ex asin_diff(const ex & x, unsigned diff_param) +static ex asin_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx asin(x) -> 1/sqrt(1-x^2) return power(1-power(x,_ex2()),_ex_1_2()); } -REGISTER_FUNCTION(asin, asin_eval, asin_evalf, asin_diff, NULL); +REGISTER_FUNCTION(asin, asin_eval, asin_evalf, asin_deriv, NULL); ////////// // inverse cosine (arc cosine) @@ -477,15 +477,15 @@ static ex acos_eval(const ex & x) return acos(x).hold(); } -static ex acos_diff(const ex & x, unsigned diff_param) +static ex acos_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx acos(x) -> -1/sqrt(1-x^2) return _ex_1()*power(1-power(x,_ex2()),_ex_1_2()); } -REGISTER_FUNCTION(acos, acos_eval, acos_evalf, acos_diff, NULL); +REGISTER_FUNCTION(acos, acos_eval, acos_evalf, acos_deriv, NULL); ////////// // inverse tangent (arc tangent) @@ -514,15 +514,15 @@ static ex atan_eval(const ex & x) return atan(x).hold(); } -static ex atan_diff(const ex & x, unsigned diff_param) +static ex atan_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx atan(x) -> 1/(1+x^2) return power(_ex1()+power(x,_ex2()), _ex_1()); } -REGISTER_FUNCTION(atan, atan_eval, atan_evalf, atan_diff, NULL); +REGISTER_FUNCTION(atan, atan_eval, atan_evalf, atan_deriv, NULL); ////////// // inverse tangent (atan2(y,x)) @@ -548,11 +548,11 @@ static ex atan2_eval(const ex & y, const ex & x) return atan2(y,x).hold(); } -static ex atan2_diff(const ex & y, const ex & x, unsigned diff_param) +static ex atan2_deriv(const ex & y, const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param<2); + GINAC_ASSERT(deriv_param<2); - if (diff_param==0) { + if (deriv_param==0) { // d/dy atan(y,x) return x*power(power(x,_ex2())+power(y,_ex2()),_ex_1()); } @@ -560,7 +560,7 @@ static ex atan2_diff(const ex & y, const ex & x, unsigned diff_param) return -y*power(power(x,_ex2())+power(y,_ex2()),_ex_1()); } -REGISTER_FUNCTION(atan2, atan2_eval, atan2_evalf, atan2_diff, NULL); +REGISTER_FUNCTION(atan2, atan2_eval, atan2_evalf, atan2_deriv, NULL); ////////// // hyperbolic sine (trigonometric function) @@ -604,15 +604,15 @@ static ex sinh_eval(const ex & x) return sinh(x).hold(); } -static ex sinh_diff(const ex & x, unsigned diff_param) +static ex sinh_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx sinh(x) -> cosh(x) return cosh(x); } -REGISTER_FUNCTION(sinh, sinh_eval, sinh_evalf, sinh_diff, NULL); +REGISTER_FUNCTION(sinh, sinh_eval, sinh_evalf, sinh_deriv, NULL); ////////// // hyperbolic cosine (trigonometric function) @@ -656,15 +656,15 @@ static ex cosh_eval(const ex & x) return cosh(x).hold(); } -static ex cosh_diff(const ex & x, unsigned diff_param) +static ex cosh_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx cosh(x) -> sinh(x) return sinh(x); } -REGISTER_FUNCTION(cosh, cosh_eval, cosh_evalf, cosh_diff, NULL); +REGISTER_FUNCTION(cosh, cosh_eval, cosh_evalf, cosh_deriv, NULL); ////////// // hyperbolic tangent (trigonometric function) @@ -708,9 +708,9 @@ static ex tanh_eval(const ex & x) return tanh(x).hold(); } -static ex tanh_diff(const ex & x, unsigned diff_param) +static ex tanh_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx tanh(x) -> 1-tanh(x)^2 return _ex1()-power(tanh(x),_ex2()); @@ -719,7 +719,7 @@ static ex tanh_diff(const ex & x, unsigned diff_param) static ex tanh_series(const ex & x, const symbol & s, const ex & pt, int order) { // method: - // Taylor series where there is no pole falls back to tanh_diff. + // Taylor series where there is no pole falls back to tanh_deriv. // On a pole simply expand sinh(x)/cosh(x). const ex x_pt = x.subs(s==pt); if (!(2*I*x_pt/Pi).info(info_flags::odd)) @@ -728,7 +728,7 @@ static ex tanh_series(const ex & x, const symbol & s, const ex & pt, int order) return (sinh(x)/cosh(x)).series(s, pt, order+2); } -REGISTER_FUNCTION(tanh, tanh_eval, tanh_evalf, tanh_diff, tanh_series); +REGISTER_FUNCTION(tanh, tanh_eval, tanh_evalf, tanh_deriv, tanh_series); ////////// // inverse hyperbolic sine (trigonometric function) @@ -757,15 +757,15 @@ static ex asinh_eval(const ex & x) return asinh(x).hold(); } -static ex asinh_diff(const ex & x, unsigned diff_param) +static ex asinh_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx asinh(x) -> 1/sqrt(1+x^2) return power(_ex1()+power(x,_ex2()),_ex_1_2()); } -REGISTER_FUNCTION(asinh, asinh_eval, asinh_evalf, asinh_diff, NULL); +REGISTER_FUNCTION(asinh, asinh_eval, asinh_evalf, asinh_deriv, NULL); ////////// // inverse hyperbolic cosine (trigonometric function) @@ -800,15 +800,15 @@ static ex acosh_eval(const ex & x) return acosh(x).hold(); } -static ex acosh_diff(const ex & x, unsigned diff_param) +static ex acosh_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx acosh(x) -> 1/(sqrt(x-1)*sqrt(x+1)) return power(x+_ex_1(),_ex_1_2())*power(x+_ex1(),_ex_1_2()); } -REGISTER_FUNCTION(acosh, acosh_eval, acosh_evalf, acosh_diff, NULL); +REGISTER_FUNCTION(acosh, acosh_eval, acosh_evalf, acosh_deriv, NULL); ////////// // inverse hyperbolic tangent (trigonometric function) @@ -840,15 +840,15 @@ static ex atanh_eval(const ex & x) return atanh(x).hold(); } -static ex atanh_diff(const ex & x, unsigned diff_param) +static ex atanh_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); // d/dx atanh(x) -> 1/(1-x^2) return power(_ex1()-power(x,_ex2()),_ex_1()); } -REGISTER_FUNCTION(atanh, atanh_eval, atanh_evalf, atanh_diff, NULL); +REGISTER_FUNCTION(atanh, atanh_eval, atanh_evalf, atanh_deriv, NULL); #ifndef NO_NAMESPACE_GINAC } // namespace GiNaC diff --git a/ginac/inifcns_zeta.cpp b/ginac/inifcns_zeta.cpp index 51f9700c..63637374 100644 --- a/ginac/inifcns_zeta.cpp +++ b/ginac/inifcns_zeta.cpp @@ -74,14 +74,14 @@ static ex zeta1_eval(const ex & x) return zeta(x).hold(); } -static ex zeta1_diff(const ex & x, unsigned diff_param) +static ex zeta1_deriv(const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param==0); + GINAC_ASSERT(deriv_param==0); return zeta(_ex1(), x); } -const unsigned function_index_zeta1 = function::register_new("zeta", zeta1_eval, zeta1_evalf, zeta1_diff, NULL); +const unsigned function_index_zeta1 = function::register_new("zeta", zeta1_eval, zeta1_evalf, zeta1_deriv, NULL); ////////// // Derivatives of Riemann's Zeta-function zeta(0,x)==zeta(x) @@ -98,11 +98,11 @@ static ex zeta2_eval(const ex & n, const ex & x) return zeta(n, x).hold(); } -static ex zeta2_diff(const ex & n, const ex & x, unsigned diff_param) +static ex zeta2_deriv(const ex & n, const ex & x, unsigned deriv_param) { - GINAC_ASSERT(diff_param<2); + GINAC_ASSERT(deriv_param<2); - if (diff_param==0) { + if (deriv_param==0) { // d/dn zeta(n,x) throw(std::logic_error("cannot diff zeta(n,x) with respect to n")); } @@ -110,7 +110,7 @@ static ex zeta2_diff(const ex & n, const ex & x, unsigned diff_param) return zeta(n+1,x); } -const unsigned function_index_zeta2 = function::register_new("zeta", zeta2_eval, NULL, zeta2_diff, NULL); +const unsigned function_index_zeta2 = function::register_new("zeta", zeta2_eval, NULL, zeta2_deriv, NULL); #ifndef NO_NAMESPACE_GINAC } // namespace GiNaC diff --git a/ginac/mul.cpp b/ginac/mul.cpp index 1b051abb..6a32fb58 100644 --- a/ginac/mul.cpp +++ b/ginac/mul.cpp @@ -462,6 +462,24 @@ ex mul::simplify_ncmul(const exvector & v) const // protected +/** Implementation of ex::diff() for a product. It applies the product rule. + * @see ex::diff */ +ex mul::derivative(const symbol & s) const +{ + exvector new_seq; + new_seq.reserve(seq.size()); + + // D(a*b*c)=D(a)*b*c+a*D(b)*c+a*b*D(c) + for (unsigned i=0; i!=seq.size(); i++) { + epvector sub_seq=seq; + sub_seq[i] = split_ex_to_pair(sub_seq[i].coeff* + power(sub_seq[i].rest,sub_seq[i].coeff-1)* + sub_seq[i].rest.diff(s)); + new_seq.push_back((new mul(sub_seq,overall_coeff))->setflag(status_flags::dynallocated)); + } + return (new add(new_seq))->setflag(status_flags::dynallocated); +} + int mul::compare_same_type(const basic & other) const { return inherited::compare_same_type(other); diff --git a/ginac/mul.h b/ginac/mul.h index de047f45..1a017417 100644 --- a/ginac/mul.h +++ b/ginac/mul.h @@ -71,7 +71,6 @@ public: int ldegree(const symbol & s) const; ex coeff(const symbol & s, int n=1) const; ex eval(int level=0) const; - ex diff(const symbol & s) const; ex series(const symbol & s, const ex & point, int order) const; ex normal(lst &sym_lst, lst &repl_lst, int level=0) const; numeric integer_content(void) const; @@ -80,6 +79,7 @@ public: exvector get_indices(void) const; ex simplify_ncmul(const exvector & v) const; protected: + ex derivative(const symbol & s) const; int compare_same_type(const basic & other) const; bool is_equal_same_type(const basic & other) const; unsigned return_type(void) const; diff --git a/ginac/ncmul.cpp b/ginac/ncmul.cpp index a970a8b2..7cd80149 100644 --- a/ginac/ncmul.cpp +++ b/ginac/ncmul.cpp @@ -538,6 +538,13 @@ ex ncmul::thisexprseq(exvector * vp) const // protected +/** Implementation of ex::diff() for a non-commutative product. It always returns 0. + * @see ex::diff */ +ex ncmul::derivative(const symbol & s) const +{ + return _ex0(); +} + int ncmul::compare_same_type(const basic & other) const { return inherited::compare_same_type(other); diff --git a/ginac/ncmul.h b/ginac/ncmul.h index b79b0ea6..b5cc1669 100644 --- a/ginac/ncmul.h +++ b/ginac/ncmul.h @@ -75,12 +75,12 @@ public: ex expand(unsigned options=0) const; ex coeff(const symbol & s, int n=1) const; ex eval(int level=0) const; - ex diff(const symbol & s) const; ex subs(const lst & ls, const lst & lr) const; exvector get_indices(void) const; ex thisexprseq(const exvector & v) const; ex thisexprseq(exvector * vp) const; protected: + ex derivative(const symbol & s) const; int compare_same_type(const basic & other) const; unsigned return_type(void) const; unsigned return_type_tinfo(void) const; diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp index 149f049c..e504186a 100644 --- a/ginac/numeric.cpp +++ b/ginac/numeric.cpp @@ -545,6 +545,14 @@ ex numeric::evalf(int level) const // protected +/** Implementation of ex::diff() for a numeric. It always returns 0. + * + * @see ex::diff */ +ex numeric::derivative(const symbol & s) const +{ + return _ex0(); +} + int numeric::compare_same_type(const basic & other) const { GINAC_ASSERT(is_exactly_of_type(other, numeric)); @@ -634,8 +642,14 @@ numeric numeric::power(const numeric & other) const static const numeric * _num1p=&_num1(); if (&other==_num1p) return *this; - if (::zerop(*value) && other.is_real() && ::minusp(realpart(*other.value))) - throw (std::overflow_error("division by zero")); + if (::zerop(*value)) { + if (::zerop(*other.value)) + throw (std::domain_error("numeric::eval(): pow(0,0) is undefined")); + else if (other.is_real() && !::plusp(realpart(*other.value))) + throw (std::overflow_error("numeric::eval(): division by zero")); + else + return _num0(); + } return numeric(::expt(*value,*other.value)); } @@ -682,8 +696,14 @@ const numeric & numeric::power_dyn(const numeric & other) const static const numeric * _num1p=&_num1(); if (&other==_num1p) return *this; - if (::zerop(*value) && other.is_real() && ::minusp(realpart(*other.value))) - throw (std::overflow_error("division by zero")); + if (::zerop(*value)) { + if (::zerop(*other.value)) + throw (std::domain_error("numeric::eval(): pow(0,0) is undefined")); + else if (other.is_real() && !::plusp(realpart(*other.value))) + throw (std::overflow_error("numeric::eval(): division by zero")); + else + return _num0(); + } return static_cast((new numeric(::expt(*value,*other.value)))-> setflag(status_flags::dynallocated)); } @@ -1659,15 +1679,6 @@ ostream& operator<<(ostream& os, const _numeric_digits & e) bool _numeric_digits::too_late = false; -////////// -// utility functions -////////// - -const numeric &ex_to_numeric(const ex &e) -{ - return static_cast(*e.bp); -} - /** Accuracy in decimal digits. Only object of this type! Can be set using * assignment from C++ unsigned ints and evaluated like any built-in type. */ _numeric_digits Digits; diff --git a/ginac/numeric.h b/ginac/numeric.h index 6c1f9f2d..03fcb431 100644 --- a/ginac/numeric.h +++ b/ginac/numeric.h @@ -129,12 +129,12 @@ public: bool info(unsigned inf) const; ex eval(int level=0) const; ex evalf(int level=0) const; - ex diff(const symbol & s) const; ex normal(lst &sym_lst, lst &repl_lst, int level=0) const; numeric integer_content(void) const; ex smod(const numeric &xi) const; numeric max_coefficient(void) const; protected: + ex derivative(const symbol & s) const; int compare_same_type(const basic & other) const; bool is_equal_same_type(const basic & other) const; unsigned calchash(void) const { @@ -323,8 +323,13 @@ ex PiEvalf(void); ex EulerGammaEvalf(void); ex CatalanEvalf(void); + // utility functions -const numeric &ex_to_numeric(const ex &e); +inline const numeric &ex_to_numeric(const ex &e) +{ + return static_cast(*e.bp); +} + #ifndef NO_NAMESPACE_GINAC } // namespace GiNaC diff --git a/ginac/power.cpp b/ginac/power.cpp index 89ba78bc..a85bc79f 100644 --- a/ginac/power.cpp +++ b/ginac/power.cpp @@ -29,6 +29,7 @@ #include "add.h" #include "mul.h" #include "numeric.h" +#include "inifcns.h" #include "relational.h" #include "symbol.h" #include "archive.h" @@ -353,7 +354,10 @@ ex power::eval(int level) const // ^(x,0) -> 1 (0^0 also handled here) if (eexponent.is_zero()) - return _ex1(); + if (ebasis.is_zero()) + throw (std::domain_error("power::eval(): pow(0,0) is undefined")); + else + return _ex1(); // ^(x,1) -> x if (eexponent.is_equal(_ex1())) @@ -514,6 +518,21 @@ ex power::simplify_ncmul(const exvector & v) const // protected +/** Implementation of ex::diff() for a power. + * @see ex::diff */ +ex power::derivative(const symbol & s) const +{ + if (exponent.info(info_flags::real)) { + // D(b^r) = r * b^(r-1) * D(b) (faster than the formula below) + return mul(mul(exponent, power(basis, exponent - _ex1())), basis.diff(s)); + } else { + // D(b^e) = b^e * (D(e)*ln(b) + e*D(b)/b) + return mul(power(basis, exponent), + add(mul(exponent.diff(s), log(basis)), + mul(mul(exponent, basis.diff(s)), power(basis, -1)))); + } +} + int power::compare_same_type(const basic & other) const { GINAC_ASSERT(is_exactly_of_type(other, power)); diff --git a/ginac/power.h b/ginac/power.h index 13dfd5ff..7a76217d 100644 --- a/ginac/power.h +++ b/ginac/power.h @@ -73,12 +73,12 @@ public: ex coeff(const symbol & s, int n=1) const; ex eval(int level=0) const; ex evalf(int level=0) const; - ex diff(const symbol & s) const; ex series(const symbol & s, const ex & point, int order) const; ex subs(const lst & ls, const lst & lr) const; ex normal(lst &sym_lst, lst &repl_lst, int level=0) const; ex simplify_ncmul(const exvector & v) const; protected: + ex derivative(const symbol & s) const; int compare_same_type(const basic & other) const; unsigned return_type(void) const; unsigned return_type_tinfo(void) const; diff --git a/ginac/pseries.cpp b/ginac/pseries.cpp index 459b4692..7fbf7311 100644 --- a/ginac/pseries.cpp +++ b/ginac/pseries.cpp @@ -298,6 +298,32 @@ ex pseries::subs(const lst & ls, const lst & lr) const return (new pseries(var, point.subs(ls, lr), new_seq))->setflag(status_flags::dynallocated); } +/** Implementation of ex::diff() for a power series. It treats the series as a + * polynomial. + * @see ex::diff */ +ex pseries::derivative(const symbol & s) const +{ + if (s == var) { + epvector new_seq; + epvector::const_iterator it = seq.begin(), itend = seq.end(); + + // FIXME: coeff might depend on var + while (it != itend) { + if (is_order_function(it->rest)) { + new_seq.push_back(expair(it->rest, it->coeff - 1)); + } else { + ex c = it->rest * it->coeff; + if (!c.is_zero()) + new_seq.push_back(expair(c, it->coeff - 1)); + } + it++; + } + return pseries(var, point, new_seq); + } else { + return *this; + } +} + /* * Construct ordinary polynomial out of series diff --git a/ginac/pseries.h b/ginac/pseries.h index 1f69ae4b..046c838e 100644 --- a/ginac/pseries.h +++ b/ginac/pseries.h @@ -66,8 +66,9 @@ public: ex eval(int level=0) const; ex evalf(int level=0) const; ex normal(lst &sym_lst, lst &repl_lst, int level=0) const; - ex diff(const symbol & s) const; ex subs(const lst & ls, const lst & lr) const; +protected: + ex derivative(const symbol & s) const; // non-virtual functions in this class public: diff --git a/ginac/symbol.cpp b/ginac/symbol.cpp index 43927dc3..1a8ef59c 100644 --- a/ginac/symbol.cpp +++ b/ginac/symbol.cpp @@ -259,6 +259,19 @@ ex symbol::subs(const lst & ls, const lst & lr) const // protected +/** Implementation of ex::diff() for single differentiation of a symbol. + * It returns 1 or 0. + * + * @see ex::diff */ +ex symbol::derivative(const symbol & s) const +{ + if (compare_same_type(s)) { + return _ex0(); + } else { + return _ex1(); + } +} + int symbol::compare_same_type(const basic & other) const { GINAC_ASSERT(is_of_type(other,symbol)); diff --git a/ginac/symbol.h b/ginac/symbol.h index 13515c47..6ab13d12 100644 --- a/ginac/symbol.h +++ b/ginac/symbol.h @@ -81,11 +81,11 @@ public: int ldegree(const symbol & s) const; ex coeff(const symbol & s, int n = 1) const; ex eval(int level = 0) const; - ex diff(const symbol & s) const; ex series(const symbol & s, const ex & point, int order) const; ex normal(lst &sym_lst, lst &repl_lst, int level=0) const; ex subs(const lst & ls, const lst & lr) const; protected: + ex derivative(const symbol & s) const; int compare_same_type(const basic & other) const; bool is_equal_same_type(const basic & other) const; unsigned return_type(void) const; @@ -96,7 +96,6 @@ protected: public: void assign(const ex & value); void unassign(void); - ex diff(const symbol & s, unsigned nth) const; void setname(const string & n) {name=n;} string getname(void) const {return name;} private: diff --git a/ginac/utils.h b/ginac/utils.h index 755881a1..fa6f54a5 100644 --- a/ginac/utils.h +++ b/ginac/utils.h @@ -34,7 +34,7 @@ namespace GiNaC { #endif // ndef NO_NAMESPACE_GINAC template -string ToString(T const & t) +string ToString(const T & t) { char buf[256]; ostrstream(buf,sizeof(buf)) << t << ends; diff --git a/ginsh/Makefile.in b/ginsh/Makefile.in index b2a7cfab..4611377e 100644 --- a/ginsh/Makefile.in +++ b/ginsh/Makefile.in @@ -64,6 +64,7 @@ ARCHIVE_VERSION = @ARCHIVE_VERSION@ AS = @AS@ CC = @CC@ CINT = @CINT@ +CINTSYSDIR = @CINTSYSDIR@ CXX = @CXX@ CXXCPP = @CXXCPP@ DLLTOOL = @DLLTOOL@ @@ -316,7 +317,7 @@ distdir: $(DISTFILES) @for file in $(DISTFILES); do \ d=$(srcdir); \ if test -d $$d/$$file; then \ - cp -pr $$/$$file $(distdir)/$$file; \ + cp -pr $$d/$$file $(distdir)/$$file; \ else \ test -f $(distdir)/$$file \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ -- 2.44.0