From kreckel at thep.physik.uni-mainz.de Thu Aug 2 13:59:28 2001 From: kreckel at thep.physik.uni-mainz.de (Richard B. Kreckel) Date: Thu, 2 Aug 2001 13:59:28 +0200 (CEST) Subject: A move away from CLN? In-Reply-To: Message-ID: On Tue, 31 Jul 2001, I wrote: > Talking about KAI's C++ compiler, I just tested it. [...] Talking about Intel's Reference Compiler, I just tested the x86-edition, version 5.0beta for Linux on the CLN/GiNaC system. It detected a few minor glitches in the GiNaC code that went undetected by all GCC versions and by KAI and Portland Group. Those are being fixed in our CVS tree. The Intel compiler is really good w.r.t. ISO standard conformance. With the usual two preprocessor settings it compiled vanilla CLN-1.1.2 statically and passed all the checks. Then it came to GiNaC's timings and there the Intel compiler showed it is *not* doing a good job. Maybe if one tunes the whole system for Pentium-IV or such the picture will change. Maybe switching on Intel's global optimizations would help, too. I couldn't do that because the compiler chose to segfault every time I tried. :-( Without more ado, here are the timings in seconds (static, stripped binaries) on a P-III 800: commutative expansion and substitution (a.k.a. Denny Fliegner's test) size GCC 3 Intel-C++ 5 Ratio 50 0.08 0.11 1.38 100 0.35 0.50 1.42 200 1.57 2.19 1.39 Laurent series expansion of Gamma function order GCC 3 Intel-C++ 5 Ratio 15 0.27 0.38 1.41 20 1.219 1.74 1.42 25 4.879 6.73 1.38 determinant of univariate symbolic Vandermonde matrices dim GCC 3 Intel-C++ 5 Ratio 6x 6 0.006 0.010 1.67 8x 8 0.11 0.15 1.36 10x10 1.01 1.52 1.50 determinant of polyvariate symbolic Toeplitz matrices dim GCC 3 Intel-C++ 5 Ratio 6x 6 0.065 0.08 1.23 7x 7 0.30 0.39 1.30 8x 8 1.32 1.66 1.26 Lewis-Wester test A (divide factorials) GCC 3 Intel-C++ 5 Ratio 0.11 0.56 5.09 Lewis-Wester test B (sum of rational numbers) GCC 3 Intel-C++ 5 Ratio 0.010 0.026 2.60 Lewis-Wester test C (gcd of big integers) GCC 3 Intel-C++ 5 Ratio 0.149 0.71 4.76 Lewis-Wester test D (normalized sum of rational fcns) GCC 3 Intel-C++ 5 Ratio 0.309 0.72 2.32 Lewis-Wester test E (normalized sum of rational fcns) GCC 3 Intel-C++ 5 Ratio 0.25 0.43 1.72 Lewis-Wester test F (gcd of 2-var polys) GCC 3 Intel-C++ 5 Ratio 0.032 0.05 1.56 Lewis-Wester test G (gcd of 3-var polys) GCC 3 Intel-C++ 5 Ratio 1.08 2.39 2.21 Lewis-Wester test H (det of 80x80 Hilbert) GCC 3 Intel-C++ 5 Ratio 4.509 7.09 1.57 Lewis-Wester test I (invert rank 40 Hilbert) GCC 3 Intel-C++ 5 Ratio 1.30 1.98 1.52 Lewis-Wester test J (check rank 40 Hilbert) GCC 3 Intel-C++ 5 Ratio 0.74 1.07 1.45 Lewis-Wester test K (invert rank 70 Hilbert) GCC 3 Intel-C++ 5 Ratio 8.81 13.67 1.55 Lewis-Wester test L (check rank 70 Hilbert) GCC 3 Intel-C++ 5 Ratio 4.35 6.55 1.51 Lewis-Wester test M1 (26x26 sparse, det) GCC 3 Intel-C++ 5 Ratio 0.17 0.24 1.41 Lewis-Wester test N (poly at rational fcns) GCC 3 Intel-C++ 5 Ratio 483.47 512.52 1.06 Lewis-Wester test P (det of sparse rank 101) GCC 3 Intel-C++ 5 Ratio 0.59 0.73 1.24 Lewis-Wester test P' (det of less sparse rank 101) GCC 3 Intel-C++ 5 Ratio 2.76 4.03 1.46 computation of an antipode in Yukawa theory GCC 3 Intel-C++ 5 Ratio 59.78 75.21 1.25 One could argue that this result is restricted to x86 and the situation looks different on real RISC machines. However, after trying some simple template-heavy tests with Sun's WorkShop 5.0 for UltraSparc we realized that GCC-3.0 performs better on real C++ code, even on that platform. I hope this helps debunk the two myths that GCC does not perform well and that CLN/GiNaC is not portable. Happy heavy hacking -richy. -- Richard Kreckel From kreckel at thep.physik.uni-mainz.de Wed Aug 8 11:55:34 2001 From: kreckel at thep.physik.uni-mainz.de (Richard B. Kreckel) Date: Wed, 8 Aug 2001 11:55:34 +0200 (CEST) Subject: GiNaC/ginsh ginsh_parser.yy In-Reply-To: <200108071940.f77Jet214739@doraemon.physik.uni-mainz.de> Message-ID: This patch... On Tue, 7 Aug 2001, Christian Bauer wrote: > Update of /home/cvs/GiNaC/ginsh > > Modified Files: > ginsh_parser.yy > Log Message: > - increased compatibility with RedHat's readline-4.2-1 package ...has broken compatibility with Readline 4.1 on all our Debian Potato boxen. I've looked into it but don't understand one thing: why were there changes necessary in sections that should be #ifdef'ed out when compiling with libreadline-4.2? Christian, can you fix this? Regards -richy. -- Richard Kreckel This libreadline nightmare makes me slightly sick. Why does the maintainer not release 4.3 *with* fine-grained version control before 4.2 screws up all upcoming Distros? And then there is the C++-brokenness. SuSE did not get it right. They seem to ship with two libreadlines now and compile all their stuff to the old one! Debian fixed it only after agonizing for a few weeks. Let's hope RedHat get's it right now. From mriedel at neuearbeit.de Wed Aug 8 19:27:51 2001 From: mriedel at neuearbeit.de (Marko Riedel) Date: Wed, 8 Aug 2001 19:27:51 +0200 (CEST) Subject: GiNaC memory leak? Message-ID: <15217.29851.165955.969488@linuxsexi.neuearbeit.de> Greetings. I am sending some code that I wrote in order to solve a differential equation. You run the compiled program with a command-line argument telling it what terms to use. Interesting values are e.g. 10, 14, 16 and 19. (The higher values take some time to compute.) Warning! When you run the program on the higher values, it starts consuming huge amounts of memory. On a SuSE Linux machine the OS eventually kills the process. What is going on here? The program solves a system of equations with a 1000 x 1000 approx. coefficient matrix. What is all the memory being used for? Take, say 32 bytes per entry; the system should then allocate about 32M of memory. In fact it tries to allocate more than 512M of memory! Best regards, Marko Riedel ---------------------------------------------------------------------- #include #include #include using namespace std; using namespace GiNaC; static symbol u("u"); static symbol z("z"); static symbol l1("l1"); static symbol l2("l2"); static symbol phi("phi"); static void extracteqs(ex eq, lst *l) { int i, j; ex c1, c2; for(i=eq.ldegree(z); i<=eq.degree(z); i++){ c1=eq.coeff(z, i); for(j=eq.ldegree(u); j<=eq.degree(u); j++){ c2=c1.coeff(u, j); if(is_ex_of_type(c2, numeric)){ if(c2!=0){ cerr << "inconsistency: " << i << " " << j << endl; exit(-1); } } else{ (*l).append(c2==0); cerr << (*l).nops() << endl; } } } } int main(int argc, char **argv) { int maxcoeff, i, j; if(argc!=2){ cout << argv[0] << " " << endl; exit(-1); } sscanf(argv[1], "%d", &maxcoeff); if(maxcoeff<1){ cout << "argument " << maxcoeff << " out of range" << endl; exit(-2); } ex rt, lf1, lf2; lst vs; rt=0; lf1=0; lf2=0; for(i=0; i Message-ID: Hi there, You have just proven Richy's second law: 1) Heuristics can be made to work in 1-epsilon of all cases. 2) Real problems tend to concentrate in the epsilon corner. :-) Your problem is the heuristics in the routine matrix::solve(). I have just run your problem with 16 as input value and found that you have a sparse 456x456 matrix that you try to solve for 456 variables. Most of the matrix entries are small integer values with 83 exceptions where integers multiplied with (-1+u)^(-1) appear. The heuristics chooses Gaussian elimination only if no symbolic entries appear in the matrix and I am quite surprised to see Bareiss' elimination perform so poor for your case. Well, you hit the epsilon corner, it appears. In any case, Gaussian elimination can solve your problem, it took about 20 minutes here (whereupon it returned an empty solution set). You have three options: 1) Don't use lsolve(). Build a matrix from the equation system, test if the system turned out to be linear and fill the variable matrix just like lsolve does. Then call matrix::solve() with a hint for the algorithm as last argument. 2) Patch your personal library of GiNaC by adding an algorithmic hint as last argument in ginac/inifcns.cpp by changing the line solution = sys.solve(vars,rhs); to something like solution = sys.solve(vars,rhs,solve_algo::gauss); and use that library instead. But then you have disabled Heuristics completely and you may screw up in other cases. 3) Let lsolve() accept an algorithmic hint. Pass that along to matrix::solve(). Test it. Send us a patch and we'll include it. Regards -richy. PS: BTW, for arguments 10 and 14 your program tells me something about inconsistencies. PPS: You shouldn't write is_ex_of_type(c2, numeric). Write is_a(c2) instead. -- Richard Kreckel On Wed, 8 Aug 2001, Marko Riedel wrote: > Greetings. > > I am sending some code that I wrote in order to solve a differential > equation. You run the compiled program with a command-line argument > telling it what terms to use. Interesting values are e.g. 10, 14, 16 > and 19. (The higher values take some time to compute.) > > Warning! When you run the program on the higher values, it starts > consuming huge amounts of memory. On a SuSE Linux machine the OS > eventually kills the process. What is going on here? The program > solves a system of equations with a 1000 x 1000 approx. coefficient > matrix. What is all the memory being used for? Take, say 32 bytes per > entry; the system should then allocate about 32M of memory. In fact it > tries to allocate more than 512M of memory! > > Best regards, > > Marko Riedel > > ---------------------------------------------------------------------- > > #include > #include > #include > > using namespace std; > using namespace GiNaC; > > static symbol u("u"); > static symbol z("z"); > static symbol l1("l1"); > static symbol l2("l2"); > static symbol phi("phi"); > > static void extracteqs(ex eq, lst *l) > { > int i, j; > ex c1, c2; > > for(i=eq.ldegree(z); i<=eq.degree(z); i++){ > c1=eq.coeff(z, i); > for(j=eq.ldegree(u); j<=eq.degree(u); j++){ > c2=c1.coeff(u, j); > if(is_ex_of_type(c2, numeric)){ > if(c2!=0){ > cerr << "inconsistency: " > << i << " " << j << endl; > exit(-1); > } > } > else{ > (*l).append(c2==0); > cerr << (*l).nops() << endl; > } > } > } > } > > int main(int argc, char **argv) > { > int maxcoeff, i, j; > > if(argc!=2){ > cout << argv[0] << " " << endl; > exit(-1); > } > > sscanf(argv[1], "%d", &maxcoeff); > if(maxcoeff<1){ > cout << "argument " << maxcoeff > << " out of range" << endl; > exit(-2); > } > > ex rt, lf1, lf2; > lst vs; > > rt=0; lf1=0; lf2=0; > for(i=0; i for(j=0; j symbol a; > > rt+=a*pow(z, i)*pow(u, j); > vs.append(a); > > if(i symbol b, c; > > lf1+=b*pow(z, i)*pow(u, j); > lf2+=c*pow(z, i)*pow(u, j); > vs.append(b); > vs.append(c); > } > } > } > > cerr << rt << endl; > cerr << lf1 << endl; > cerr << lf2 << endl; > > cerr << vs << endl; > > ex s, sf, sf1, sf2; > > sf=pow(1-u, 11)*pow(1-z, 7)*pow(1-z*u, 7); > sf1=pow(1-u, 9)*pow(1-z, 5)*pow(1-z*u, 5); > sf2=pow(1-u, 10)*pow(1-z, 2)*pow(1-z*u, 2); > s=rt/sf1+ > lf1*u*log(1/(1-z))/sf2+ > lf2*log(1/(1-z*u))/sf2; > > ex f, rz, rzv, rzu, rzvu; > > f=(u-u*u*z*z)/pow(1-z, 2)/pow(1-z*u, 2); > rz=1/pow(1-z, 2); > rzv=1/pow(1-z, 2); > rzu=rz.subs(z==z*u); > rzvu=rzv.subs(z==z*u); > > ex t1, t2, t3, t4, t5, t6, t7, t8, t9; > > t1=6*u*u*rzu *f; > t2=6*u*u*rzvu*f; > t3=6*u*u*rzu *phi; > > t4=6*u*u*rzu *rz; > t5=6*u*u*rzvu*rz; > t6=6*u*u*rzu *rzv; > > t7=6* rz *f; > t8=6* rzv *f; > t9=6* rz *phi; > > ex rhs1, rhs2; > > rhs1=(t1+t2+t4+t5+t6+t7+t8).normal(); > rhs2=(t3+t9).normal(); > > ex eq, eq1; > > eq=(s.diff(z, 2)-rhs1-rhs2.subs(phi==s)) > .subs(lst(log(1/(1-z))==l1, log(1/(1-z*u))==l2)) > .expand(); > eq1=0; > > for(i=0; i eq1+=(eq.op(i)*sf).normal().expand(); > cerr << "expand: " << i << " " << eq.nops() << endl; > } > > ex leq1=eq1.coeff(l1, 1), leq2=eq1.coeff(l2, 1); > eq1=eq1.subs(lst(l1==0, l2==0)); > > lst ceqs; > > ex s0=(s.subs(z==0)*pow(1-u, 9)).normal(); > ex sz0=(s.diff(z).subs(z==0)*pow(1-u, 9)).normal(); > > ex i0=(u*pow(1-u, 9)).expand(); > ex iz0=((4*u+4*u*u)*pow(1-u, 9)).expand(); > > cerr << "extract initial: 1" << endl; > extracteqs(s0-i0, &ceqs); > cerr << "extract initial: 2" << endl; > extracteqs(sz0-iz0, &ceqs); > > cerr << "extract: 1" << endl; > extracteqs(eq1, &ceqs); > cerr << "eqs: " << ceqs.nops() << endl; > cerr << "extract: 2" << endl; > extracteqs(leq1, &ceqs); > cerr << "eqs: " << ceqs.nops() << endl; > cerr << "extract: 3" << endl; > extracteqs(leq2, &ceqs); > cerr << "eqs: " << ceqs.nops() << endl; > > ex sl; > > cerr << "solving: " > << ceqs.nops() << " " > << vs.nops() << " ..." << endl; > try{ > sl=lsolve(ceqs, vs); > } > catch(exception &e){ > cerr << e.what() << endl; > exit(-3); > } > cout << sl << endl; > > lst zlist; > for(i=0; i zlist.append(vs.op(i)==0); > } > > ex result; > result=s.subs(sl).subs(zlist); > cout << result << endl; > > archive a; > a.archive_ex(result, "result"); > > char fname[80]; > sprintf(fname, "fixedpoints%d.gar", maxcoeff); > > ofstream out(fname); > out << a; > out.close(); > } From kreckel at thep.physik.uni-mainz.de Wed Aug 8 21:27:13 2001 From: kreckel at thep.physik.uni-mainz.de (Richard B. Kreckel) Date: Wed, 8 Aug 2001 21:27:13 +0200 (CEST) Subject: GiNaC memory leak? In-Reply-To: <15217.29851.165955.969488@linuxsexi.neuearbeit.de> Message-ID: On Wed, 8 Aug 2001, Marko Riedel wrote: > Warning! When you run the program on the higher values, it starts > consuming huge amounts of memory. On a SuSE Linux machine the OS > eventually kills the process. What is going on here? I forgot to address the subject: no, there is no indication of a memory leak here. Cheers -richy. -- Richard Kreckel From mriedel at neuearbeit.de Thu Aug 9 13:25:45 2001 From: mriedel at neuearbeit.de (Marko Riedel) Date: Thu, 9 Aug 2001 13:25:45 +0200 (CEST) Subject: GiNaC memory leak? In-Reply-To: References: <15217.29851.165955.969488@linuxsexi.neuearbeit.de> Message-ID: <15218.29357.745048.311313@linuxsexi.neuearbeit.de> Greetings. Thanks for your extensive commentary! I *really* appreciate it. In fact if there are terms that include (1-u)^(-1), then there is a bug in my program. I will try to find the bug. I think your having responded so quickly and extensively is really terrific! Best regards, Marko Riedel From pearu at cens.ioc.ee Sun Aug 12 23:08:20 2001 From: pearu at cens.ioc.ee (Pearu Peterson) Date: Sun, 12 Aug 2001 23:08:20 +0200 (EET) Subject: ex_to templates Message-ID: Hi! Since ex_to_*() are announced deprecated with the corresponding replacements ex_to<*>() then what about ex_to_nonconst_*()? Will there be ex_to_nonconst<*>()? It just seems logical to have ones. Regards, Pearu From duraid at fl.net.au Tue Aug 14 15:07:38 2001 From: duraid at fl.net.au (Duraid Madina) Date: Tue, 14 Aug 2001 23:07:38 +1000 Subject: Most elegant way to get from (ex) to (void *)? Message-ID: <3B79229A.8070004@fl.net.au> Hi all, What's the most elegant way (okay, fastest way) to translate between expressions and plain-old arrays of bytes? (of course, I am interested in both directions!) Right now I've got a really kludgy system that takes the expression, 'archives' it, sends that archive into an 'strstream' buffer, and then grabs the 'string' backing that strstream, et voila. Any better ideas? ;-) Thanks in advance, Duraid From cbauer at student.physik.uni-mainz.de Tue Aug 14 17:04:52 2001 From: cbauer at student.physik.uni-mainz.de (Christian Bauer) Date: Tue, 14 Aug 2001 17:04:52 +0200 Subject: Most elegant way to get from (ex) to (void *)? In-Reply-To: <3B79229A.8070004@fl.net.au> References: <3B79229A.8070004@fl.net.au> Message-ID: <20010814170452.A28191@student.physik.uni-mainz.de> Hi! On Tue, Aug 14, 2001 at 11:07:38PM +1000, Duraid Madina wrote: > Right now I've got a really kludgy system that takes the expression, > 'archives' it, sends that archive into an 'strstream' buffer, and then > grabs the 'string' backing that strstream, et voila. Yes, that's exactly what the archives are meant for. Bye, Christian -- / Coding on PowerPC and proud of it \/ http://www.uni-mainz.de/~bauec002/ From pearu at cens.ioc.ee Thu Aug 16 12:41:52 2001 From: pearu at cens.ioc.ee (Pearu Peterson) Date: Thu, 16 Aug 2001 12:41:52 +0200 (EET) Subject: bug(?): garbage produced by archive_node.get_string Message-ID: Hi, Note that if one uses static void my_print2(const archive_node & n); from the GiNaC Tutorial for expressions that has lenghty string then the result of get_string produces some garbage at the end of string. For example, the following code int main(void) { ex e = pow(200, 500); archive ar(e, "e"); my_print2(ar.get_top_node(0)); cout << endl; return 0; } outputs numeric(number="3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589376000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000|????_+ at x????") I am using GiNaC 0.9.2, gcc 2.95.2, Linux MD 7.0. Best regards, Pearu From kreckel at thep.physik.uni-mainz.de Thu Aug 16 13:56:08 2001 From: kreckel at thep.physik.uni-mainz.de (Richard B. Kreckel) Date: Thu, 16 Aug 2001 13:56:08 +0200 (CEST) Subject: bug(?): garbage produced by archive_node.get_string In-Reply-To: Message-ID: On Thu, 16 Aug 2001, Pearu Peterson wrote: > Note that if one uses > static void my_print2(const archive_node & n); > from the GiNaC Tutorial for expressions that has lenghty string then the > result of get_string produces some garbage at the end of string. > For example, the following code > > int main(void) > { > ex e = pow(200, 500); > archive ar(e, "e"); > my_print2(ar.get_top_node(0)); cout << endl; > return 0; > } > > outputs > > numeric(number="32733906078961418700131896968275991522166420460430647894832913680961337964046745548832700923259041571508866841275600710092172565458853930533285275893760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000! 00! > 000000000000000000000000000000000000000000000000000|????_+ at x????") > > I am using GiNaC 0.9.2, gcc 2.95.2, Linux MD 7.0. Pearu, this is unreproducible: it doesn't produce that garbage here. What version of CLN are you using and what were the exact compiler switches CLN and GiNaC were compiled with? Can other people please try to see if they can reproduce Pearu's problem on their system? Thanks. Regards -richy. -- Richard Kreckel From pearu at cens.ioc.ee Thu Aug 16 14:19:13 2001 From: pearu at cens.ioc.ee (Pearu Peterson) Date: Thu, 16 Aug 2001 14:19:13 +0200 (EET) Subject: bug(?): garbage produced by archive_node.get_string In-Reply-To: Message-ID: On Thu, 16 Aug 2001, Richard B. Kreckel wrote: > Pearu, this is unreproducible: it doesn't produce that garbage here. What > version of CLN are you using and what were the exact compiler switches CLN > and GiNaC were compiled with? CLN is 1.1. And the command line is: g++ test_archive.cpp -lcln -lginac > Can other people please try to see if they can reproduce Pearu's problem > on their system? Thanks. I have the same problem on Debian potato. With 'g++ -v' it outputs (if it helps): Reading specs from /usr/lib/gcc-lib/i386-linux/2.95.2/specs gcc version 2.95.2 20000220 (Debian GNU/Linux) /usr/lib/gcc-lib/i386-linux/2.95.2/cpp -lang-c++ -v -D__GNUC__=2 -D__GNUG__=2 -D__GNUC_MINOR__=95 -D__cplusplus -D__ELF__ -Dunix -D__i386__ -Dlinux -D__ELF__ -D__unix__ -D__i386__ -D__linux__ -D__unix -D__linux -Asystem(posix) -D__EXCEPTIONS -Acpu(i386) -Amachine(i386) -Di386 -D__i386 -D__i386__ test_archive.cpp /tmp/ccTyAyTw.ii GNU CPP version 2.95.2 20000220 (Debian GNU/Linux) (i386 Linux/ELF) #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g++-3 /usr/local/include /usr/lib/gcc-lib/i386-linux/2.95.2/include /usr/include End of search list. The following default directories have been omitted from the search path: /usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include End of omitted list. /usr/lib/gcc-lib/i386-linux/2.95.2/cc1plus /tmp/ccTyAyTw.ii -quiet -dumpbase test_archive.cc -version -o /tmp/ccxGXIip.s GNU C++ version 2.95.2 20000220 (Debian GNU/Linux) (i386-linux) compiled by GNU C version 2.95.2 20000220 (Debian GNU/Linux). as -V -Qy -o /tmp/cc0FqGDp.o /tmp/ccxGXIip.s GNU assembler version 2.9.5 (i386-linux) using BFD version 2.9.5.0.37 /usr/lib/gcc-lib/i386-linux/2.95.2/collect2 -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/gcc-lib/i386-linux/2.95.2/crtbegin.o -L/usr/lib/gcc-lib/i386-linux/2.95.2 /tmp/cc0FqGDp.o -lcln -lginac -lstdc++ -lm -lgcc -lc -lgcc /usr/lib/gcc-lib/i386-linux/2.95.2/crtend.o /usr/lib/crtn.o Pearu From kreckel at thep.physik.uni-mainz.de Thu Aug 16 15:29:32 2001 From: kreckel at thep.physik.uni-mainz.de (Richard B. Kreckel) Date: Thu, 16 Aug 2001 15:29:32 +0200 (CEST) Subject: bug(?): garbage produced by archive_node.get_string In-Reply-To: Message-ID: On Thu, 16 Aug 2001, Pearu Peterson wrote: > On Thu, 16 Aug 2001, Richard B. Kreckel wrote: > > > Pearu, this is unreproducible: it doesn't produce that garbage here. What > > version of CLN are you using and what were the exact compiler switches CLN > > and GiNaC were compiled with? > > CLN is 1.1. > And the command line is: > g++ test_archive.cpp -lcln -lginac > > > Can other people please try to see if they can reproduce Pearu's problem > > on their system? Thanks. > > I have the same problem on Debian potato. > > With 'g++ -v' it outputs (if it helps): > > Reading specs from /usr/lib/gcc-lib/i386-linux/2.95.2/specs > gcc version 2.95.2 20000220 (Debian GNU/Linux) ^^^^^^^^ Still negative. I also tried it on a RedHat 7.1.93 (Roswell) box and Debian's testing distribution (Woody). The string above looks like a vanilla Debian box. We use the very same compiler over here. We use CLN-1.1.2 but AFAICT there were no problems on Intel-arch with older versions. Are you really running CLN-1.1 and not 1.1.1 or 1.1.2? Are you using a Debian package of CLN? If so, which is the precise version? Can you update to CLN-1.1.2 and see if the problem persists? If so, could you please send us the exact lines how to reproduce it, beginning from configure-flags, the values of CXXFLAGS, CPPFLAGS, LDFLAGS and all this for both CLN and GiNaC? Regards -richy. -- Richard Kreckel From kreckel at thep.physik.uni-mainz.de Thu Aug 16 22:19:27 2001 From: kreckel at thep.physik.uni-mainz.de (Richard B. Kreckel) Date: Thu, 16 Aug 2001 22:19:27 +0200 (CEST) Subject: No subject Message-ID: We are psyched to announce GiNaC 0.9.3. This release is even more fat-, meta-tag-, cholesterol- and bug-free than earlier versions: * Series expansion is now much more consistent for very small order expansion, giving some users unprecedented expressiveness and * lsolve() accepts an algorithmic hint as parameter so one can squeeze out ultimate performance. Get your copy as long as our supply of this groundbreaking product lasts! From pearu at cens.ioc.ee Fri Aug 17 20:16:14 2001 From: pearu at cens.ioc.ee (Pearu Peterson) Date: Fri, 17 Aug 2001 20:16:14 +0200 (EET) Subject: bug(?): garbage produced by archive_node.get_string In-Reply-To: Message-ID: Hi again, On Thu, 16 Aug 2001, Richard B. Kreckel wrote: > Still negative. I also tried it on a RedHat 7.1.93 (Roswell) box and > Debian's testing distribution (Woody). The string above looks like a > vanilla Debian box. We use the very same compiler over here. We use > CLN-1.1.2 but AFAICT there were no problems on Intel-arch with older > versions. Are you really running CLN-1.1 and not 1.1.1 or 1.1.2? Are you > using a Debian package of CLN? If so, which is the precise version? Can > you update to CLN-1.1.2 and see if the problem persists? If so, could you > please send us the exact lines how to reproduce it, beginning from > configure-flags, the values of CXXFLAGS, CPPFLAGS, LDFLAGS and all this > for both CLN and GiNaC? Now I have updated CLN from a tar-balls and GiNaC from CVS: > cln-config --version --libs --cppflags 1.1.2 -L/opt/cln-1.1.2/lib -lcln -lgmp -I/opt/cln-1.1.2/include (GMP is 3.1.1) > ginac-config --version --libs --cppflags 0.9.3 -L/opt/GiNaC-0.9.3-17Aug2001/lib -lginac -L/opt/cln-1.1.2/lib -lcln -lgmp -I/opt/GiNaC-0.9.3-17Aug2001/include -I/opt/cln-1.1.2/include No CXXFLAGS, CPPFLAGS, LDFLAGS were specified during the configurations. > uname -a Linux ath 2.2.18-mosix #1 Tue Jan 9 11:20:28 EET 2001 i686 unknown Debian 2.2 > gcc -v Reading specs from /usr/lib/gcc-lib/i386-linux/2.95.2/specs gcc version 2.95.2 20000220 (Debian GNU/Linux) I have reduced the test case to: /* test.cpp */ #include using namespace GiNaC; using namespace std; int main(void) { ex e = pow(200, 500); archive ar(e, "e"); const archive_node &n = ar.get_top_node(0); n.printraw(cout); cout << endl; string x; n.find_string("number", x); cout << x << endl; cout << "length=" << x.length() << " (should be 1152)" << endl; return 0; } Compilation: g++ test.cpp -lginac -lcln And the output is (basic * 0x8052fa8 = 32733906078961418700131896968275991522166420460430647894832913680961337964046745548832700923259041571508866841275600710092172565458853930533285275893760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) string "class" 1 string "number" 3 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589376000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000????m*@???? length=1040 (should be 1152) It seems to me that something gets wrong in C++, not in GiNaC. I have run out of ideas how to fix this garbage --- it is a third Linux system that has this same problem (two Debians, one Mandrake, all have the same gcc version). Any hints are appreciated. Regards, Pearu From kreckel at thep.physik.uni-mainz.de Fri Aug 17 21:05:24 2001 From: kreckel at thep.physik.uni-mainz.de (Richard B. Kreckel) Date: Fri, 17 Aug 2001 21:05:24 +0200 (CEST) Subject: bug(?): garbage produced by archive_node.get_string In-Reply-To: Message-ID: Hi, On Fri, 17 Aug 2001, Pearu Peterson wrote: > > uname -a > Linux ath 2.2.18-mosix #1 Tue Jan 9 11:20:28 EET 2001 i686 unknown ^^^^^ Just a random bubble: are all affected boxen running Mosixized kernels? > It seems to me that something gets wrong in C++, not in GiNaC. > I have run out of ideas how to fix this garbage --- it is a third > Linux system that has this same problem (two Debians, one Mandrake, all > have the same gcc version). Any hints are appreciated. I am still having no success reproducing this garbage on a variety of boxen, including strange IRIX machines. As to potato, I just recall that our's isn't vanilla. When I was porting to GCC-3.0 I ran into a well-documented problem with binutils on that distribution so I had to manually update them: higgs:~$ ld -v GNU ld version 2.10.91 (with BFD 2.10.1.0.2) Everything else is vanilla, though. Especially g++. However, I don't see how binutils may affect the running behaviour. Mind updating them nevertheless? Do you have any machine where it works or is this a 100% failure? Regards -richy. -- Richard Kreckel From pearu at cens.ioc.ee Fri Aug 17 21:39:45 2001 From: pearu at cens.ioc.ee (Pearu Peterson) Date: Fri, 17 Aug 2001 21:39:45 +0200 (EET) Subject: bug(?): garbage produced by archive_node.get_string In-Reply-To: Message-ID: On Fri, 17 Aug 2001, Richard B. Kreckel wrote: > On Fri, 17 Aug 2001, Pearu Peterson wrote: > > > uname -a > > Linux ath 2.2.18-mosix #1 Tue Jan 9 11:20:28 EET 2001 i686 unknown > ^^^^^ > Just a random bubble: are all affected boxen running Mosixized kernels? Nope. > > It seems to me that something gets wrong in C++, not in GiNaC. > > I have run out of ideas how to fix this garbage --- it is a third > > Linux system that has this same problem (two Debians, one Mandrake, all > > have the same gcc version). Any hints are appreciated. > > I am still having no success reproducing this garbage on a variety of > boxen, including strange IRIX machines. As to potato, I just recall that > our's isn't vanilla. When I was porting to GCC-3.0 I ran into a > well-documented problem with binutils on that distribution so I had to > manually update them: > higgs:~$ ld -v > GNU ld version 2.10.91 (with BFD 2.10.1.0.2) Our Linux boxes have: GNU ld version 2.9.5 (with BFD 2.9.5.0.37) - Debian GNU ld version 2.9.5 (with BFD 2.9.5.0.16) - MD > Everything else is vanilla, though. Especially g++. However, I don't see > how binutils may affect the running behaviour. Mind updating them > nevertheless? Do you have any machine where it works or is this a 100% > failure? So far the 100%. I haven't tried our Linux Alpha boxes (RedHat 6.1) yet. There I need to install GiNaC first ... Thanks, Pearu From pearu at cens.ioc.ee Sat Aug 18 02:11:17 2001 From: pearu at cens.ioc.ee (Pearu Peterson) Date: Sat, 18 Aug 2001 02:11:17 +0200 (EET) Subject: bug(?): garbage produced by archive_node.get_string In-Reply-To: Message-ID: Hi, I finally tracked down what caused this garbage. It was due to void numeric::archive(archive_node &n) const in numeric.cpp where a fixed size buffer is defined if HAVE_SSTREAM is undefined. If I made the following changes $ diff numeric.cpp numeric.cpp.orig 307c307,308 < std::ostrstream s; --- > char buf[1024]; > std::ostrstream s(buf, 1024); 329c330,332 < n.add_string("number", s.str()); --- > s << ends; > std::string str(buf); > n.add_string("number", str); then the garbage disappered. So, why you define fixed size buffer if ostrstream has the same functionality as ostringstream (at least in gcc system)? Regards, Pearu From kreckel at thep.physik.uni-mainz.de Sat Aug 18 17:30:11 2001 From: kreckel at thep.physik.uni-mainz.de (Richard B. Kreckel) Date: Sat, 18 Aug 2001 17:30:11 +0200 (CEST) Subject: bug(?): garbage produced by archive_node.get_string In-Reply-To: Message-ID: Hi, On Sat, 18 Aug 2001, Pearu Peterson wrote: > I finally tracked down what caused this garbage. > It was due to > void numeric::archive(archive_node &n) const > in numeric.cpp where a fixed size buffer is defined if HAVE_SSTREAM is > undefined. Doh! I was completely forgetting that our gcc-2.95.2 is vanilla with the exception that I have dropped the attached file into /usr/include/g++-3/. I recommend that you do the same. GCC-2.95.3 has this hack, too. And GCC-3.0 has a cleaner implementation of course. Applying self-LART... > If I made the following changes > > $ diff numeric.cpp numeric.cpp.orig > 307c307,308 > < std::ostrstream s; > --- > > char buf[1024]; > > std::ostrstream s(buf, 1024); > 329c330,332 > < n.add_string("number", s.str()); > --- > > s << ends; > > std::string str(buf); > > n.add_string("number", str); > > then the garbage disappered. > > So, why you define fixed size buffer if ostrstream has the same > functionality as ostringstream (at least in gcc system)? I didn't know this works. We were under the impression that fixed-size buffers are a must for ostrstream. This misunderstanding was probably due to exercise 26 in chapter 21 of Stroustrup's TC++PL3 where only the ctor we use is mentioned. Looking at the standard's Annex D one finds the ctor you use indeed documented, so this fix would probably be sane. I won't fix it though, since ostrstream is officially deprecated anyhow and may eventually be thrown out of GiNaC entirely in favor of ostringstream. If you go through the sources and grep for the dozen or so occurences, fix them and send us a patch, they could still be applied (for a transistion period). Regards -richy. -- Richard Kreckel -------------- next part -------------- /* This is part of libio/iostream, providing -*- C++ -*- input/output. Copyright (C) 2000 Free Software Foundation This file is part of the GNU IO Library. This library 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, or (at your option) any later version. This library 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 library; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, if you link this library with files compiled with a GNU compiler to produce an executable, this does not cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License. */ /* Written by Magnus Fromreide (magfr at lysator.liu.se). */ #ifndef __SSTREAM__ #define __SSTREAM__ #include #include #include namespace std { class stringbuf : public streambuf { public: typedef char char_type; typedef int int_type; typedef streampos pos_type; typedef streamoff off_type; explicit stringbuf(int which=ios::in|ios::out) : streambuf(which), buf(), mode(static_cast(which)), rpos(0), bufsize(1) { } explicit stringbuf(const std::string &s, int which=ios::in|ios::out) : streambuf(which), buf(s), mode(static_cast(which)), bufsize(1) { if(mode & ios::in) { setg(&defbuf, &defbuf + bufsize, &defbuf + bufsize); } if(mode & ios::out) { setp(&defbuf, &defbuf + bufsize); } rpos = (mode & ios::ate ? s.size() : 0); } std::string str() const { const_cast(this)->sync(); // Sigh, really ugly hack return buf; }; void str(const std::string& s) { buf = s; if(mode & ios::in) { gbump(egptr() - gptr()); } if(mode & ios::out) { pbump(pbase() - pptr()); } rpos = (mode & ios::ate ? s.size() : 0); } protected: inline virtual int sync(); inline virtual int overflow(int = EOF); inline virtual int underflow(); private: std::string buf; ios::open_mode mode; std::string::size_type rpos; streamsize bufsize; char defbuf; }; class stringstreambase : virtual public ios { protected: stringbuf __my_sb; public: std::string str() const { return dynamic_cast(_strbuf)->str(); } void str(const std::string& s) { clear(); dynamic_cast(_strbuf)->str(s); } stringbuf* rdbuf() { return &__my_sb; } protected: stringstreambase(int which) : __my_sb(which) { init (&__my_sb); } stringstreambase(const std::string& s, int which) : __my_sb(s, which) { init (&__my_sb); } }; class istringstream : public stringstreambase, public istream { public: istringstream(int which=ios::in) : stringstreambase(which) { } istringstream(const std::string& s, int which=ios::in) : stringstreambase(s, which) { } }; class ostringstream : public stringstreambase, public ostream { public: ostringstream(int which=ios::out) : stringstreambase(which) { } ostringstream(const std::string& s, int which=ios::out) : stringstreambase(s, which) { } }; class stringstream : public stringstreambase, public iostream { public: stringstream(int which=ios::in|ios::out) : stringstreambase(which) { } stringstream(const std::string &s, int which=ios::in|ios::out) : stringstreambase(s, which) { } }; } inline int std::stringbuf::sync() { if((mode & ios::out) == 0) return EOF; streamsize n = pptr() - pbase(); if(n) { buf.replace(rpos, std::string::npos, pbase(), n); if(buf.size() - rpos != n) return EOF; rpos += n; pbump(-n); gbump(egptr() - gptr()); } return 0; } inline int std::stringbuf::overflow(int ch) { if((mode & ios::out) == 0) return EOF; streamsize n = pptr() - pbase(); if(n && sync()) return EOF; if(ch != EOF) { std::string::size_type oldSize = buf.size(); buf.replace(rpos, std::string::npos, ch); if(buf.size() - oldSize != 1) return EOF; ++rpos; } return 0; } inline int std::stringbuf::underflow() { sync(); if((mode & ios::in) == 0) { return EOF; } if(rpos >= buf.size()) { return EOF; } std::string::size_type n = egptr() - eback(); std::string::size_type s; s = buf.copy(eback(), n, rpos); pbump(pbase() - pptr()); gbump(eback() - gptr()); int res = (0377 & buf[rpos]); rpos += s; return res; } #endif /* not __SSTREAM__ */ From pearu at cens.ioc.ee Sat Aug 18 21:25:06 2001 From: pearu at cens.ioc.ee (Pearu Peterson) Date: Sat, 18 Aug 2001 21:25:06 +0200 (EET) Subject: GiNaC/ginac basic.cpp numeric.cpp operators.cpp power.cpp pseries.cpp symbol.cpp wildcard.cpp In-Reply-To: <200108181746.TAA13801@higgs.physik.uni-mainz.de> Message-ID: > - carried on with felonious plot about making ex::bp private. Sorry that I haven't checked out the details of this evil plot as I am a bit afraid it will broke something in my project (pyginac - Python interface to GiNaC). But here follow my concerns. For this interface I use the following expressions: e.bp->precedence(); e.bp->class_name(); (GiNaC::lst &)(*(e.bp)); (GiNaC::numeric &)(*(e.bp)); (GiNaC::symbol &)(*(e.bp)); etc. where e is an ex instance. Will there be ways to write these expressions after your plot is complete? Pearu From pearu at cens.ioc.ee Sun Aug 19 09:45:25 2001 From: pearu at cens.ioc.ee (Pearu Peterson) Date: Sun, 19 Aug 2001 09:45:25 +0200 (EET) Subject: Cannot evaluate numerically 2^Pi, for instance. Message-ID: Hi, I have found that when calling evalf() method for a power instance, its exponent is not evaluated. Here follows an example that demonstrates this: include using namespace GiNaC; using namespace std; int main(void) { ex e = pow(2, Pi); cout << "e="; e.print(print_context(cout)); cout << endl; cout << "e.evalf()="; e.evalf().print(print_context(cout)); cout << endl; return 0; } The output is: e=2^Pi e.evalf()=(2.0)^Pi And I don't see anything wrong in ex power::evalf(int level) const; Do you? Regards, Pearu From pearu at cens.ioc.ee Mon Aug 20 13:31:55 2001 From: pearu at cens.ioc.ee (Pearu Peterson) Date: Mon, 20 Aug 2001 13:31:55 +0200 (EET) Subject: PROPOSAL: Dynamic creation of functions Message-ID: Dear GiNaC developers, In "What doesn't belong into GiNaC" section of GiNaC tutorial you encourage using GiNaC as a bottom of a complete CAS. I have used GiNaC in connection with Python language and found that such a combination can be very close to a perfect environment that has powerful programming capabilities with efficient symbolic algebra support. However, GiNaC lacks one important feature, that is, creating new functions in runtime. It is clear that within C++ environment it is not desired (if not impossible) as users can define their functions at the compilation stage. In scripting languages, however, new functions can be defined only in runtime. Therefore, I have been looking ways how to create new functions to GiNaC without forcing re-compilations of C++ codes. One can find different approaches for that but they all require some modifications to GiNaC sources. So, I am writing to you with a hope that these modifications could be done in GiNaC repository, rather than by me or anybody else with a similar projects, each time as a new version of GiNaC is released. After trying out many approaches, I have reached to the following conclusion: It is impossible to define dynamic functions in GiNaC because the variables function_options::eval_f,evalf_f,series_f,derivative_f must point to static functions where is impossible to determine what function called it (that is, with what serial number). Now, let me describe a solution to this problem: 1) (Interface authors) define special functions dynfunc_eval_f,etc as follows (I'll use Python C/API for illustrations): ex dynfunc_eval_f(const exvector & seq) { unsigned serial = function::current_serial; //see below (3) PyObject *func = dynfunc_eval_cache[serial]; //see below (2) /* Implement call: result = func(seq), specific to different languages */ return result; } 2) Dynamic functions are created by calling the following (a minimal implementation): void build_function(const string & name, unsigned nparams, PyObject* py_eval_func, //pointers to Python functions PyObject* py_evalf_func, ...) { function_options opts; opts = set_name(name).eval_func(dynfunc_eval_f); // NOTE: all dynamically created functions have the same eval_f. // There, using cache and serial, appropriate Python function is called. // See above (1) opts.test_and_set_params(nparams); unsigned serial = function::register_new(opts); // Store Python function in cache: dynfunc_eval_cache[serial] = py_eval_func; } where std::map dynfunc_eval_cache; is defined in the interface space (similarly are defined hooks for evalf,series,derivative). 3) The following definitions would be new to GiNaC: typedef ex (* GiNaC::eval_funcp_v)(const exvector &); function_options& function_options::eval_func(eval_funcp_v e) { use_vector_args = true; eval_f = eval_funcp(e); return *this; } class function_options { ... protected: bool use_vector_args; /* are to be set false by default */ }; class function { ... public: static unsigned current_serial; }; and in GiNaC::function::eval the following lines are added just before the 'switch (opt.nparams) {..}' statement: if (registered_functions()[serial].use_vector_args) { current_serial = serial; eval_result = ((eval_funcp_v)(registered_functions()[serial].eval_f))(seq); } else Similar hooks are added to functions GiNaC::function::eval,series,pderivative. What do you think? Can I can implement/test these modifications and send you them as a patch? Thanks, Pearu From kreckel at thep.physik.uni-mainz.de Mon Aug 20 14:42:39 2001 From: kreckel at thep.physik.uni-mainz.de (Richard B. Kreckel) Date: Mon, 20 Aug 2001 14:42:39 +0200 (CEST) Subject: GiNaC/ginac basic.cpp numeric.cpp operators.cpp power.cpp pseries.cpp symbol.cpp wildcard.cpp In-Reply-To: Message-ID: On Sat, 18 Aug 2001, Pearu Peterson wrote: > > - carried on with felonious plot about making ex::bp private. > > Sorry that I haven't checked out the details of this evil plot as I am > a bit afraid it will broke something in my project (pyginac - Python > interface to GiNaC). But here follow my concerns. > For this interface I use the following expressions: > e.bp->precedence(); > e.bp->class_name(); > (GiNaC::lst &)(*(e.bp)); > (GiNaC::numeric &)(*(e.bp)); > (GiNaC::symbol &)(*(e.bp)); > etc. > where e is an ex instance. > > Will there be ways to write these expressions after your plot is complete? Short answer: don't panic. :-) Long answer: After the evil plot is completed the above won't compile, of course. Then you would have to write `ex_to(e).precedence()' or `ex_to(e).precedence()' or whatever (it doesn't really matter) for the first example. Please note that by virtue of ex_to's return value being a reference, it is still susceptible to dynamic type-dispatch, which is what your concern boils down to. You can (and should) already write it this way. Have a look at the last batch of changes to see how these things translate. In particular, the usage of `foo::is_equal(const basic &)' inside `foo::degree(const ex &)' is somewhat touchy, but the last changes compile to exactly the same: Regards -richy. -- Richard Kreckel From kreckel at thep.physik.uni-mainz.de Mon Aug 20 17:41:57 2001 From: kreckel at thep.physik.uni-mainz.de (Richard B. Kreckel) Date: Mon, 20 Aug 2001 17:41:57 +0200 (CEST) Subject: Cannot evaluate numerically 2^Pi, for instance. In-Reply-To: Message-ID: On Sun, 19 Aug 2001, Pearu Peterson wrote: [...] > The output is: > e=2^Pi > e.evalf()=(2.0)^Pi > > And I don't see anything wrong in > ex power::evalf(int level) const; > Do you? After staring at it for an hour or two, yes. It's most embarrassing. Here is the fix: diff -r1.66 power.cpp 493c493 < if (!is_ex_exactly_of_type(eexponent,numeric)) --- > if (!is_ex_exactly_of_type(exponent,numeric)) See the problem? :-) Thank you for reporting this! -richy. -- Richard Kreckel From pearu at cens.ioc.ee Mon Aug 20 18:56:54 2001 From: pearu at cens.ioc.ee (Pearu Peterson) Date: Mon, 20 Aug 2001 18:56:54 +0200 (EET) Subject: PROPOSAL: Dynamic creation of functions In-Reply-To: Message-ID: On Mon, 20 Aug 2001, Pearu Peterson wrote: > What do you think? Can I can implement/test these modifications and send > you them as a patch? Meanwhile I implemented these hooks, and it works perfectly. Please find the patch attached to this message. To apply it, 'cd ginac/' and hit 'patch -p0 < function.pl.diff-0.9.3'. As a result, I can now construct GiNaC functions directly in Python. Here is an example of the corresponding Python session: import ginac class mysin: nparams = 1 def eval(self, x): return self(x, hold=1) def derivative(self, x, diff_param): return ginac.cos(x) f = ginac.build_function(mysin) x = ginac.symbol('x') print f(x) # outputs: mysin(x) print f(x).diff(x) # outputs: cos(x) I hope that you find my patch useful for creating interfaces between GiNaC and various scripting languages. Regards, Pearu -------------- next part -------------- --- function.pl.orig Mon Aug 20 13:33:50 2001 +++ function.pl Mon Aug 20 15:15:12 2001 @@ -239,6 +239,10 @@ $typedef_derivative_funcp $typedef_series_funcp // end of generated lines +typedef ex (* eval_funcp_v)(const exvector &); +typedef ex (* evalf_funcp_v)(const exvector &); +typedef ex (* derivative_funcp_v)(const exvector &, unsigned); +typedef ex (* series_funcp_v)(const exvector &, const relational &, int, unsigned); class function_options { @@ -257,6 +261,11 @@ $derivative_func_interface $series_func_interface // end of generated lines + function_options& function_options::eval_func(eval_funcp_v e); + function_options& function_options::evalf_func(evalf_funcp_v ef); + function_options& function_options::derivative_func(derivative_funcp_v d); + function_options& function_options::series_func(series_funcp_v s); + function_options & set_return_type(unsigned rt, unsigned rtt=0); function_options & do_not_evalf_params(void); function_options & remember(unsigned size, unsigned assoc_size=0, @@ -290,6 +299,11 @@ unsigned remember_assoc_size; unsigned remember_strategy; + bool eval_use_vector_args; + bool evalf_use_vector_args; + bool derivative_use_vector_args; + bool series_use_vector_args; + unsigned functions_with_same_name; ex symtree; @@ -354,10 +368,10 @@ void store_remember_table(ex const & result) const; public: static unsigned register_new(function_options const & opt); + static unsigned current_serial; static unsigned find_function(const std::string &name, unsigned nparams); unsigned get_serial(void) const {return serial;} std::string get_name(void) const; - // member variables protected: @@ -433,6 +447,8 @@ namespace GiNaC { +unsigned function::current_serial = 0; + ////////// // helper class function_options ////////// @@ -461,6 +477,10 @@ evalf_params_first = true; use_return_type = false; use_remember = false; + eval_use_vector_args = false; + evalf_use_vector_args = false; + derivative_use_vector_args = false; + series_use_vector_args = false; functions_with_same_name = 1; symtree = 0; } @@ -488,6 +508,30 @@ $derivative_func_implementation $series_func_implementation // end of generated lines +function_options& function_options::eval_func(eval_funcp_v e) +{ + eval_use_vector_args = true; + eval_f = eval_funcp(e); + return *this; +} +function_options& function_options::evalf_func(evalf_funcp_v ef) +{ + evalf_use_vector_args = true; + evalf_f = evalf_funcp(ef); + return *this; +} +function_options& function_options::derivative_func(derivative_funcp_v d) +{ + derivative_use_vector_args = true; + derivative_f = derivative_funcp(d); + return *this; +} +function_options& function_options::series_func(series_funcp_v s) +{ + series_use_vector_args = true; + series_f = series_funcp(s); + return *this; +} function_options & function_options::set_return_type(unsigned rt, unsigned rtt) { @@ -756,7 +800,11 @@ if (use_remember && lookup_remember_table(eval_result)) { return eval_result; } - + current_serial = serial; + if (registered_functions()[serial].eval_use_vector_args) { + eval_result = ((eval_funcp_v)(registered_functions()[serial].eval_f))(seq); + } + else switch (opt.nparams) { // the following lines have been generated for max. ${maxargs} parameters ${eval_switch_statement} @@ -792,6 +840,9 @@ if (registered_functions()[serial].evalf_f==0) { return function(serial,eseq).hold(); } + current_serial = serial; + if (registered_functions()[serial].evalf_use_vector_args) + return ((evalf_funcp_v)(registered_functions()[serial].evalf_f))(seq); switch (registered_functions()[serial].nparams) { // the following lines have been generated for max. ${maxargs} parameters ${evalf_switch_statement} @@ -835,6 +886,15 @@ return basic::series(r, order); } ex res; + current_serial = serial; + if (registered_functions()[serial].series_use_vector_args) { + try { + res = ((series_funcp_v)(registered_functions()[serial].series_f))(seq, r, order, options); + } catch (do_taylor) { + res = basic::series(r, order, options); + } + return res; + } switch (registered_functions()[serial].nparams) { // the following lines have been generated for max. ${maxargs} parameters ${series_switch_statement} @@ -938,7 +998,9 @@ // No derivative defined? Then return abstract derivative object if (registered_functions()[serial].derivative_f == NULL) return fderivative(serial, diff_param, seq); - + current_serial = serial; + if (registered_functions()[serial].derivative_use_vector_args) + return ((derivative_funcp_v)(registered_functions()[serial].derivative_f))(seq, diff_param); switch (registered_functions()[serial].nparams) { // the following lines have been generated for max. ${maxargs} parameters ${diff_switch_statement} From kreckel at thep.physik.uni-mainz.de Mon Aug 20 19:38:32 2001 From: kreckel at thep.physik.uni-mainz.de (Richard B. Kreckel) Date: Mon, 20 Aug 2001 19:38:32 +0200 (CEST) Subject: PROPOSAL: Dynamic creation of functions In-Reply-To: Message-ID: On Mon, 20 Aug 2001, Pearu Peterson wrote: > Meanwhile I implemented these hooks, and it works perfectly. > Please find the patch attached to this message. Thanks a lot for your patch, I am currently investigating it. This won't be finished today, hopefully tomorrow. Just one question: You know that this issue has been discussed already with no final consensus? The last rant is archived at . (I don't see clear yet. This email is just to make sure we don't miss any opportunity.) Regards -richy. -- Richard Kreckel From pearu at cens.ioc.ee Mon Aug 20 20:16:00 2001 From: pearu at cens.ioc.ee (Pearu Peterson) Date: Mon, 20 Aug 2001 20:16:00 +0200 (EET) Subject: PROPOSAL: Dynamic creation of functions In-Reply-To: Message-ID: On Mon, 20 Aug 2001, Richard B. Kreckel wrote: > Thanks a lot for your patch, I am currently investigating it. This won't > be finished today, hopefully tomorrow. Just one question: You know that > this issue has been discussed already with no final consensus? The last > rant is archived at . > (I don't see clear yet. This email is just to make sure we don't miss any > opportunity.) At the time I overlooked this message and then forgot, though it seemed relevant. However, my patch will not certainly solve your problem. In Python one can define functions on fly --- that is what you are trying to establish in C++, if I understand this correctly. My patch just helps connecting Python and GiNaC in such a way that the problem is transformed to the Python side where it is not an acctual problem anymore. Thanks, Pearu From kreckel at thep.physik.uni-mainz.de Mon Aug 20 20:22:23 2001 From: kreckel at thep.physik.uni-mainz.de (Richard B. Kreckel) Date: Mon, 20 Aug 2001 20:22:23 +0200 (CEST) Subject: PROPOSAL: Dynamic creation of functions In-Reply-To: Message-ID: On Mon, 20 Aug 2001, Richard B. Kreckel wrote: > On Mon, 20 Aug 2001, Pearu Peterson wrote: > > Meanwhile I implemented these hooks, and it works perfectly. > > Please find the patch attached to this message. > > Thanks a lot for your patch, I am currently investigating it. This won't > be finished today, hopefully tomorrow. Just one question: You know that > this issue has been discussed already with no final consensus? The last > rant is archived at . > (I don't see clear yet. This email is just to make sure we don't miss any > opportunity.) Okay, I've looked at Peru's patch now. It is indeed quite trivial. Let me restate it: where we have foofunction_eval(const ex &x, const ex &y) with a fixed number of arguments he proposes to add an alternative where there is foofunction_eval(exvector) directly, i.e. not to do the translating effort from seq[0] to x and seq[1] to y. His patch simply adds additional support for this into function.pl along the old named arguments. Interstingly, this seems to solve a bunch of problems of scripting-interface maintainers. Alex (and Christian): May I ask you for a braindump of yours as to why we haven't done this all the time? Is it just a matter of being able to access `x' and `y' inside the implementations of foofunction_eval() or were there any other less trivial considerations? (This way all the function.{h,cpp} being generated from function.pl would be unnecessary. Not that I want to throw it out, though...) Hasta luego -richy. -- Richard Kreckel From pearu at cens.ioc.ee Tue Aug 21 10:15:48 2001 From: pearu at cens.ioc.ee (Pearu Peterson) Date: Tue, 21 Aug 2001 10:15:48 +0200 (EET) Subject: Bug in print2 of Tutorial Message-ID: Hi, Shouldn't the lines n.find_bool(name, x); n.find_unsigned(name, x); n.find_string(name, x); in static void my_print2(const archive_node & n); of the Tutorial be replaced with the following ones: n.find_bool(name, x, j); n.find_unsigned(name, x, j); n.find_string(name, x, j); ? I noticed that when extracting info from fderivative instance. I was expecting 'D[0,1](f)(x,y)' but I was getting 'D[0,0](f)(x,y)' from 'f(x,y).diff(x).diff(y)'. The change above fixed this. As I understand, then all items in property p[i] should be of the same type. Is this always true? Regards, Pearu From cbauer at student.physik.uni-mainz.de Tue Aug 21 16:51:25 2001 From: cbauer at student.physik.uni-mainz.de (Christian Bauer) Date: Tue, 21 Aug 2001 16:51:25 +0200 Subject: Bug in print2 of Tutorial In-Reply-To: References: Message-ID: <20010821165125.B619@student.physik.uni-mainz.de> Hi! On Tue, Aug 21, 2001 at 10:15:48AM +0200, Pearu Peterson wrote: > Shouldn't the lines > n.find_bool(name, x); > n.find_unsigned(name, x); > n.find_string(name, x); > in static void my_print2(const archive_node & n); of the Tutorial be > replaced with the following ones: > n.find_bool(name, x, j); > n.find_unsigned(name, x, j); > n.find_string(name, x, j); > ? Yes, the index parameter was a later addition. > As I understand, then all items in property p[i] should be of the same > type. Is this always true? Each property p[i] stores only one item of data, but the vector of properties p[] of an archive_node can contain items of different types. Bye, Christian -- / Coding on PowerPC and proud of it \/ http://www.uni-mainz.de/~bauec002/ From keith.briggs at bt.com Fri Aug 24 15:29:01 2001 From: keith.briggs at bt.com (keith.briggs at bt.com) Date: Fri, 24 Aug 2001 14:29:01 +0100 Subject: dead link at http://www.ginac.de/ Message-ID: Dear GiNaC people, Your link CLN Class Library for Numbers at http://www.ginac.de/ seems to be dead. Best wishes, Keith Dr. Keith M. Briggs Senior Mathematician, Complexity Research, BTexact Technologies email: Keith.Briggs at bt.com phone: +44(0)1473 work: 641 911 home: 625 972 fax: 647 410 web: www.btexact.com/people/briggsk2/ mail: Keith Briggs, Antares 2pp5, Adastral Park, Martlesham, Suffolk IP5 3RE, UK