match: don't modify subexpression list if expression doesn't match the pattern.
As of now the match() method modifies the list of matched subexpressions
(its second argument) even if the expression in question does not match
the pattern. Thus, this simple program
#include <ginac/ginac.h>
#include <iostream>
using namespace GiNaC;
int main(int argc, char** argv)
{
symbol x;
ex e = pow(x, 5);
ex pattern = pow(wild(), -1);
lst repl;
bool test = e.match(pattern, repl);
std::cout << "repl = " << repl << std::endl;
}
prints
repl = {x}
Such behaviour is a bit unexpected. Sometimes it confuses even GiNaC
developers, see e.g.
http://www.ginac.de/pipermail/ginac-devel/2006-April/000942.html
[BUGFIX] Reclaiming the memory allocated for static objects *is* necessary.
GiNaC allocates memory for static objects (i.e. flyweights, remember tables,
etc), but doesn't free it. This is OK if the program lifetime matches libginac
lifetime, since the OS will reclaim that memory anyway.
However, if the program lifetime is different from that of libginac, this
turns into a memory leak. This happens if someone dlopen's libginac.so, and
dlclose's it later on (read: if someone uses GiNaC via scripting language
bindings).
symbol::autoname_prefix(): there's no need for dynamical memory allocation.
remember_table::remember_tables(): likewise.
function::registered_functions(): likewise.
lib_init::~lib_init(): if library usage count drops to 0, reclaim the memory
allocated for flyweights.
symbol: get rid of assign/unassign (for performance and other reasons).
* symbol::eval() is trivial now, so compiler can inline it in some cases.
* symbol takes less memory.
* no functionality is lost (as C++ has associative arrays).
multiple zeta values: make crandall_Y_loop helper function reentrant.
* Move crB and crG variables into initcX function (the only user of these
variables).
* Pass crX coefficients to crandall_Y_loop instead of using a global variable.
* While at it make crandall_Y_loop and initcX functions static.
gcd(): allow user to override (some of) heuristics.
GiNaC tries to avoid expanding expressions while computing GCDs and applies
a number of heuristics. Usually this improves performance, but in some cases
it doesn't. Allow user to switch off heuristics.
Part 5:
* gcd(): don't use heuristic GCD algorithm if gcd_options::no_heur_gcd
flag is set.
* gcd(): don't handle partially factored expressions in a special way
if gcd_options::no_part_factored flag is set.
refactor gcd() a little bit (no functional changes).
GiNaC tries to avoid expanding expressions while computing GCDs and applies
a number of heuristics. Usually this improves performance, but in some cases
it doesn't. Allow user to switch off heuristics.
Part 4:
refactor gcd() a little bit, so subsequent patch(es) won't be so big and ugly.
introduce gcd_pf_mul: gcd helper to handle partially factored expressions.
GiNaC tries to avoid expanding expressions while computing GCDs and applies
a number of heuristics. Usually this improves performance, but in some cases
it doesn't. Allow user to switch off heuristics.
Part 3:
Move the code handling products from gcd() into a separate function. This
is *really* only code move, everything else should be considered a bug.
introduce gcd_pf_pow: gcd helper to handle partially factored expressions.
GiNaC tries to avoid expanding expressions while computing GCDs and applies
a number of heuristics. Usually this improves performance, but in some cases
it doesn't. Allow user to switch off heuristics.
Part 2:
Move the code handling powers from gcd() into a separate function. This
is *really* only code move, everything else should be considered a bug.
GiNaC tries to avoid expanding expressions while computing GCDs and applies
a number of heuristics. Usually this improves performance, but in some cases
it doesn't. Allow user to switch off heuristics.
Part 1:
* add new (optional) argument to gcd() to control its behaviour.
* introduce gcd_options structure.
N.B. No actual code changes so far, the actual handling of newly introduced
options is the subject of further patches.
inifscn_nstdsums: make functions handling Li/G transformations reentrant.
Explicitly pass the dummy symbols instead of using a global variable.
As a side effect, the code is more clear now (that's a bit subjective, but
anyway).
1. Bad performance. Parsing a sum seems to be O(N^{2 + a}) (a > 0) [1].
For example, parsing a sum (actually, a univariate polynomial) of 32768
terms takes about 90 sec. on my box, parsing a sum of 10^6 terms takes
"eternity".
2. The user is expected to provide list of all symbols in the expression.
Often this is very annoying (and useless).
3. Parser is not reentrant (bison *can* produce reentrant parsers, but that
won't solve other problems).
4. Parser is difficult to extend.
Hence the new parser.
Features:
1. Parsing large sums and products is O(N).
2. Parser is reentrant (well, almost).
3. It's possible to insert (shell style) comments inside the expressions.
4. matrices, lists, FAIL are NOT handled. Yes, this *is* a feature :-)
Limitations:
1. Error handling is a bit terse: on error exception is thrown, and that's it.
2. Binary, octal, and hexadecimal numbers can not be parsed (yet).
3. Tensors, noncommutative products, etc. can not be parsed.
Other notes:
1. ex ctor still uses the old parser.
2. ginsh still uses the old parser.
[1] Mesured by this script (requires gnuplot):
make_expression_string ()
{
printf "1 + x"
local n=2
while test $n -le $1; do
printf " + %s*x^%s" $n $n
n=$(expr $n + 1)
done
}
A complex number can have an exact real part and inexact (floating point)
imaginary part, and vice a versa. Handle these cases properly in the archiving
code instead of bailing out with a bizzare error message.
Thanks to Chris Bouchard for reporting the bug.
NOTE: this fix changes the format of GiNaC archives, so formally it breaks
the binary compatibility. However, "mixed" complex numbers (i.e. ones with
exact real part and inexact imaginary part) can not be archived with previous
versions of GiNaC, so there's nothing to break.
inifcns_nstdsums.cpp: S_num takes cl_N as an argument instead of numeric.
Implicit conversion from cl_N to numeric considered harmful.
Using GiNaC::numeric for numerical computations incurs significant
overhead, so one might want to do these computations using proper CLN
types. Unfortunately, it's not easy due to automatic conversion from
cln::cl_N to GiNaC::numeric. Here is a simple example:
cl_N x, y;
// initialize them
return sin(x) + y*exp(y);
The compiler complains about ambigously overloaded of functions, i.e.
cl_N cln::sin(const cl_N&) versus numeric GiNaC::sin(const numeric&).
Hence, I propose to disable *implicit* conversion from cl_N to numeric
(this can be done by marking the numeric ctor as `explicit').
However, this change happens to be a bit nontrivial, because that evil
conversion is used in GiNaC itself. So, I decided to rewrite those fragments
of code.
Jens Vollinga [Tue, 24 Jun 2008 19:26:58 +0000 (21:26 +0200)]
Improve heur_gcd() so it can handle rational polynomials, and add a test case.
Previously heur_gcd() worked only with integer polynomials, and did not check
if the inputs are indeed integer polynomials. That lead to an endless loop or
a miscomputed gcd.
../../sw/ginac/ginac/symbol.h: In constructor 'GiNaC::symbol::symbol()':
../../sw/ginac/ginac/symbol.h:112: warning: 'GiNaC::symbol::ret_type_tinfo' will be initialized after
../../sw/ginac/ginac/symbol.h:110: warning: 'unsigned int GiNaC::symbol::domain'
../../sw/ginac/ginac/symbol.cpp:47: warning: when initialized here
../../sw/ginac/ginac/symbol.h: In constructor 'GiNaC::symbol::symbol(const std::string&, unsigned int)':
../../sw/ginac/ginac/symbol.h:112: warning: 'GiNaC::symbol::ret_type_tinfo' will be initialized after
../../sw/ginac/ginac/symbol.h:110: warning: 'unsigned int GiNaC::symbol::domain'
../../sw/ginac/ginac/symbol.cpp:75: warning: when initialized here
../../sw/ginac/ginac/symbol.h: In constructor 'GiNaC::symbol::symbol(const std::string&, unsigned int, const void*, unsigned int)':
The warnings are a bit silly, but they can hide more useful ones.
check: indicate the test failures with non-zero exit code; split test programs.
IMNSHO parsing the output of test programs in order to check if the
tests passed is a bad idea (and it causes *real* problems, see e.g.
http://www.ginac.de/pipermail/ginac-list/2008-February/001345.html).
It's much simpler and cleaner to indicate the failure in a genuine
*NIX way: exit with nonzero code.
Jens Vollinga [Mon, 15 Oct 2007 23:39:01 +0000 (23:39 +0000)]
- info(info_flags::has_indices) now works for sums and products. It
returns true if the expression has indices (no matter dummy or free),
and false otherwise [Sheplyakov].