Richard Kreckel [Thu, 3 Feb 2011 22:48:21 +0000 (23:48 +0100)]
Merge branch 'master.msvc.support' of git://github.com/AlexeiSheplyakov/GiNaC
* 'master.msvc.support' of git://github.com/AlexeiSheplyakov/GiNaC:
Omit extra qualification (as in struct foo f() vs foo f()).
[msvc] msvc cannot handle string constants above 16k
[msvc] Yet another compiler bug work around.
[msvc] Work around strange scoping and name mangling rules.
Add few defines for msvc (__func__, __alignof__).
symmetry::compare_same_type(): const-correctness fix
clifford: fix a few GCCisms (or, not).
Don't try to tie the library version to the package version number.
Use curret:release:age to indicate ABI changes instead. Hard-code LT_RELEASE
to 1.5 to avoid spurious SONAME change (current code is binary-compatible
with GiNaC 1.5.8).
But the ability to do so is important for a lot of practical uses. So soon
after the C++98 standard was approved, a language defect report was filed
on this topic, see
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#195
The result is that compilers will be allowed to support reinterpret_cast
conversions of function pointers to other (pointers) types, and vice a versa.
Such conversions work with *current* compilers (GCC 4.x), but don't work
with older ones, hence this patch.
Fix the compliation error *for real* ... and restore performance
Commit 8bf0597dde55e4c94a2ff39f1d8130902e3d7a9b (titled as 'Fixed the parser
such that it can read in user defined classes again.') made the parser a bit
slower, especially if the input contains many terms of user-defined type.
The reason for that is quite simple: we throw and catch an exception every
time we construct an object of user-defined type:
// dirty hack to distinguish between serial numbers of functions and real
// pointers.
GiNaC::function* f = NULL;
try {
unsigned serial = (unsigned)(unsigned long)(void *)(reader->second);
f = new GiNaC::function(serial, args);
}
catch ( std::runtime_error ) {
if ( f ) delete f;
ex ret = reader->second(args);
return ret;
}
Fortunately functions are aligned and we can use much more efficient
technique to distinguish between serial and pointers to functions.
This patch is an ugly hack that does the same as the commit f38cbcd651246fb5c1294705d29399f3cbfddaf5
but without changing the ABI (so it can be used in ginac_1-5).
Richard Kreckel [Thu, 9 Dec 2010 08:18:34 +0000 (09:18 +0100)]
Make symbol::name be initialized lazily.
This fixes symbol::get_name(), which returned an empty string instead of
"symbol" followed by the serial number if the symbol's name wasn't
specified in the constructor.
Richard Kreckel [Thu, 9 Dec 2010 08:18:34 +0000 (09:18 +0100)]
Make symbol::name be initialized lazily.
This fixes symbol::get_name(), which returned an empty string instead of
"symbol" followed by the serial number if the symbol's name wasn't
specified in the constructor.
Thanks to Warren Weckesser for reporting this bug.
[PATCH 2/2] chinrem_gcd: return correct integer content when GCD is a number.
This patch fixes a silly typo and makes chinrem_gcd work correctly with
polynomials which are "almost" (up to an integer coefficient) relatively
prime.
[PATCH 1/2] extract_integer_content: check for rational numbers properly.
Commit 3d09388a (titled as `[bugfix] chinrem_gcd: handle polynomials over
rationals properly.') broke extract_integer_content: now it always returns 1.
The check for rational `integer_contnent' introduced by that commit is wrong
(since integers is a subset of rationals). Rewrite the check proprerly.
(cherry picked from commit f0fb303711b4334ce59f7da63bfa7cb49f46265f)
[PATCH 2/2] chinrem_gcd: return correct integer content when GCD is a number.
This patch fixes a silly typo and makes chinrem_gcd work correctly with
polynomials which are "almost" (up to an integer coefficient) relatively
prime.
Thanks to Ernst Moritz Hahn for a bug report and a test case.
[PATCH 1/2] extract_integer_content: check for rational numbers properly.
Commit 3d09388a (titled as `[bugfix] chinrem_gcd: handle polynomials over
rationals properly.') broke extract_integer_content: now it always returns 1.
The check for rational `integer_contnent' introduced by that commit is wrong
(since integers is a subset of rationals). Rewrite the check proprerly.
Jan Rheinländer [Mon, 20 Sep 2010 12:23:14 +0000 (12:23 +0000)]
[msvc] Work around strange scoping and name mangling rules.
1. msvc creates different symbols for a variable declared in
a namespace scope and (the same variable) in a class method
scope. That is,
// util.cpp
namespace GiNaC {
extern const ex _ex0; // [1]
}
// ex.h
namespace GiNaC {
class ex {
public:
bool is_zero() {
extern const ex _ex0;
// mangled name of _ex0 is different that of [1]
}
};
}
2. The mangled names for cv-qualified and cv-unqualified versions
of a type are different (which violates the requirements stated
in [basic.type.qualifier])
These msvc's "features" cause linking failures due to unresolved
external symbols.
Solution:
1. Declare variables (_ex0) in the GiNaC namespace scope (for msvc only).
2. Add corresponding cv-qualifier(s).
The method in question is const, therefore one should use const_iterator
to access indices. Some compilers (for instance, msvc) are very strict
about this, and won't accept (invalid) code using non-const iterator.
[bugfix] chinrem_gcd: handle polynomials over rationals properly.
* extract_integer_content():
integer_content() can also return a rational number, e.g if the expression
is a polynomial over rationals (in this case expr/content is polynomial
over integers with integer content being 1). Therefore check if
integer_content() is really an integer (and if it's not just return 1,
GCD for polynomials over a field is defined up to arbitrary element of
the field).
This fixes possible segfault when computing GCD of polynomials over
rationals (this is not theoretical, see the added test case).
[bugfix] chinrem_gcd: handle polynomials over rationals properly.
* extract_integer_content():
integer_content() can also return a rational number, e.g if the expression
is a polynomial over rationals (in this case expr/content is polynomial
over integers with integer content being 1). Therefore check if
integer_content() is really an integer (and if it's not just return 1,
GCD for polynomials over a field is defined up to arbitrary element of
the field).
This fixes possible segfault when computing GCD of polynomials over
rationals (this is not theoretical, see the added test case).
Thanks to Ernst Moritz Hahn for reporting this bug.
mul: algebraic_subs_mul(), has(): don't write beyond the end of array
algebraic_match_mul_with_mul() iterates over operands of mul, that is
for (size_t i=0; i<e.nops(); ++i)
However, the size of arrays (`vectors' in STL speak) passed to this
function is seq.size(), which is nops() - 1 for any mul object. Thus
algebraic_match_mul_with_mul() accesses beyond the arrays limit. Usually
it's not a problem, since any reasonable implementation of std::vector<bool>
packs booleans into ints (or longs). However, some STL implementations
(in particular, the one shipped with msvc) are more picky, and access
beyond the vector<bool> limits results in a segfault. Therefore let's
play safe and allocate proper number of elements (that is, nops()) for
those arrays (subsed and currsubsed).
(cherry picked from commit cbb93fadabbd56ba006902967b15b2b2aebb037c)
mul: algebraic_subs_mul(), has(): don't write beyond the end of array
algebraic_match_mul_with_mul() iterates over operands of mul, that is
for (size_t i=0; i<e.nops(); ++i)
However, the size of arrays (`vectors' in STL speak) passed to this
function is seq.size(), which is nops() - 1 for any mul object. Thus
algebraic_match_mul_with_mul() accesses beyond the arrays limit. Usually
it's not a problem, since any reasonable implementation of std::vector<bool>
packs booleans into ints (or longs). However, some STL implementations
(in particular, the one shipped with msvc) are more picky, and access
beyond the vector<bool> limits results in a segfault. Therefore let's
play safe and allocate proper number of elements (that is, nops()) for
those arrays (subsed and currsubsed).
Avoid infinite loop when unarchiving realsymbol and possymbol.
symbol::read_archive(): explicitly set status_flags::evaluated (and
status_flags::expanded) on object being unarchived. These flags get
reset by basic::operator=(const basic&) for realsymbol and possymbol,
and nothing sets (except symbol ctor), so automatic evaluation never
terminates (or rather, terminates due to a stack overflow). Therefore
it's necessary need to set status_flags::evaluated explicitly.
Avoid infinite loop when unarchiving realsymbol and possymbol.
symbol::read_archive(): explicitly set status_flags::evaluated (and
status_flags::expanded) on object being unarchived. These flags get
reset by basic::operator=(const basic&) for realsymbol and possymbol,
and nothing sets (except symbol ctor), so automatic evaluation never
terminates (or rather, terminates due to a stack overflow). Therefore
it's necessary need to set status_flags::evaluated explicitly.
Thanks to Markus Fröb for a bugreport and a test case.
Richard Kreckel [Wed, 22 Sep 2010 22:40:38 +0000 (00:40 +0200)]
Make sure add::eval() collects all numeric terms.
Apparently, add::eval() assumed that none of the elements of its epvector
has a numeric rest. However, nothing guarantees that -- in particular
evalchildren() doesn't (and actually cannot) do so. Since there are many
places where a new add is constructed directly from an epvector, enforcing
this doesn't make sense either. One example where it did fail was found by
Burgin Erocal: real_part(1+2*(sqrt(2)+1)*(sqrt(2)-1)) returned 1+2*1, not 3.
Richard Kreckel [Wed, 22 Sep 2010 22:40:38 +0000 (00:40 +0200)]
Make sure add::eval() collects all numeric terms.
Apparently, add::eval() assumed that none of the elements of its epvector
has a numeric rest. However, nothing guarantees that -- in particular
evalchildren() doesn't (and actually cannot) do so. Since there are many
places where a new add is constructed directly from an epvector, enforcing
this doesn't make sense either. One example where it did fail was found by
Burgin Erocal: real_part(1+2*(sqrt(2)+1)*(sqrt(2)-1)) returned 1+2*1, not 3.
Richard Kreckel [Wed, 15 Sep 2010 07:11:57 +0000 (09:11 +0200)]
Be more careful about final top-level substitution.
Substituting x==log(x) in exp(x) erroneously returned log(x) because of a
final subst(x==log(x)) after having eval'ed exp(log(x)) -> x. This final
substitution is wrong in the general case. On the other hand, the intent
is to syntactically substitute functions of a given kind etc. This patch
suppresses the final top-level substitution unless the intermediate result
is a container.
Thanks to Burcin Erocal for reporting this bug (originally described by
Kees van Schaik on sage-support@googlegroops.com).
Richard Kreckel [Wed, 15 Sep 2010 07:11:57 +0000 (09:11 +0200)]
Be more careful about final top-level substitution.
Substituting x==log(x) in exp(x) erroneously returned log(x) because of a
final subst(x==log(x)) after having eval'ed exp(log(x)) -> x. This final
substitution is wrong in the general case. On the other hand, the intent
is to syntactically substitute functions of a given kind etc. This patch
suppresses the final top-level substitution unless the intermediate result
is a container.
Thanks to Burcin Erocal for reporting this bug (originally described by
Kees van Schaik on sage-support@googlegroops.com).
Richard Kreckel [Mon, 13 Sep 2010 20:39:05 +0000 (22:39 +0200)]
Fix autoconf warning about AC_INIT use.
Apparently, autoconf doesn't like the angle brackets in the bug-report
argument any more. It comlains "not a literal: <ginac-list@ginac.de>".
So let's remove it. And while at it, also provide tarname and url
arguments.
Richard Kreckel [Mon, 13 Sep 2010 20:39:05 +0000 (22:39 +0200)]
Fix autoconf warning about AC_INIT use.
Apparently, autoconf doesn't like the angle brackets in the bug-report
argument any more. It comlains "not a literal: <ginac-list@ginac.de>".
So let's remove it. And while at it, also provide tarname and url
arguments.
While working on fsolve bug I've noticed the following in valgrind log:
==17455== 136 (56 direct, 80 indirect) bytes in 1 blocks are definitely lost in loss record 16 of 19
==17455== at 0x4C249C7: operator new(unsigned long) (vg_replace_malloc.c:220)
==17455== by 0x516CA70: GiNaC::power::eval(int) const (power.cpp:540)
==17455== by 0x4FC1E39: GiNaC::ex::construct_from_basic(GiNaC::basic const&) (ex.cpp:310)
==17455== by 0x406FBF: main (ex.h:255)
fsolve: avoid useless numerical evaluation of the function
Don't compute f(x) if new x is outside of the interval. We don't need that
value anyway, and the function might be difficult to compute numerically or
even ill defined outside the interval.
As a result fsolve is able to find root(s) of some weird functions.
For example
In general, ex_to is unsafe, and should be used only after proper checks.
evalf() may return non-numeric expression for various reasons (bad
convergence, floating point over- or underflow, out of memory, etc).
So let's add missing checks.
While working on fsolve bug I've noticed the following in valgrind log:
==17455== 136 (56 direct, 80 indirect) bytes in 1 blocks are definitely lost in loss record 16 of 19
==17455== at 0x4C249C7: operator new(unsigned long) (vg_replace_malloc.c:220)
==17455== by 0x516CA70: GiNaC::power::eval(int) const (power.cpp:540)
==17455== by 0x4FC1E39: GiNaC::ex::construct_from_basic(GiNaC::basic const&) (ex.cpp:310)
==17455== by 0x406FBF: main (ex.h:255)
Heap allocated objects definitely need the status_flags::dyncallocated flag.
fsolve: avoid useless numerical evaluation of the function
Don't compute f(x) if new x is outside of the interval. We don't need that
value anyway, and the function might be difficult to compute numerically or
even ill defined outside the interval.
As a result fsolve is able to find root(s) of some weird functions.
For example
In general, ex_to is unsafe, and should be used only after proper checks.
evalf() may return non-numeric expression for various reasons (bad
convergence, floating point over- or underflow, out of memory, etc).
So let's add missing checks.
Texinfo interprets @strong{Note...} as a cross reference and gives a
warning about it. Changed the text to avoid this.
(cherry picked from commit 7769ce49235ed6510785baa0a29801e3a59b563e)
Richard Kreckel [Sat, 22 May 2010 20:34:42 +0000 (22:34 +0200)]
Be more careful with conjugate(f(x)) -> f(conjugate(x)).
That identity is correct for holomorphic functions, but we have to be
careful with some functions not being holomorphic everywhere. On branch
cuts, it is wrong. For a discussion, see:
<http://www.ginac.de/pipermail/ginac-list/2010-April/001601.html>.
This patch changes the default behavior of user-defined functions. From
now on, a user-defined conjugate_func must be registered, in order to
evaluate conjugate(f(x)) -> f(conjugate(x)). This patch also adds such
functions for most initially known functions.
Richard Kreckel [Sat, 22 May 2010 20:34:42 +0000 (22:34 +0200)]
Be more careful with conjugate(f(x)) -> f(conjugate(x)).
That identity is correct for holomorphic functions, but we have to be
careful with some functions not being holomorphic everywhere. On branch
cuts, it is wrong. For a discussion, see:
<http://www.ginac.de/pipermail/ginac-list/2010-April/001601.html>.
This patch changes the default behavior of user-defined functions. From
now on, a user-defined conjugate_func must be registered, in order to
evaluate conjugate(f(x)) -> f(conjugate(x)). This patch also adds such
functions for most initially known functions.
pgcd(), chinrem_gcd(): use appropriate definition of the degree.
Effect: fixes (rare) GCD miscalculation.
pgcd() treats polynomials Z_p[x_0, ..., x_n] as R[x_0, ..., x_{n - 1}], where
R = Z_p[x_n]. Therefore one should use correct definition of the degree
(i.e. compute it w.r.t. x_0, ..., x_{n-1}, but NOT w.r.t. x_n!).
One should use appropriate definition of degree (that is, w.r.t. x_0, ..., x_n)
in chinrem_gcd() too.
pgcd(): avoid infinite loop if the first GCD candidate coincides with GCD
136 if (H_lcoeff.is_equal(lc_gcd)) {
137 if ((Hprev-H).expand().smod(pn).is_zero()) // (*)
138 continue;
The check (*) can result in infinite loop if the (very) first GCD candidate
gives the correct GCD: any subsequent iterations give the same result, so
Hprev and H will be equal (hence the infinite loop). That check is not very
useful (AFAIR I was trying to avoid extra division checks), so let's remove it.
pgcd(), chinrem_gcd(): use appropriate definition of the degree.
Effect: fixes (rare) GCD miscalculation.
pgcd() treats polynomials Z_p[x_0, ..., x_n] as R[x_0, ..., x_{n - 1}], where
R = Z_p[x_n]. Therefore one should use correct definition of the degree
(i.e. compute it w.r.t. x_0, ..., x_{n-1}, but NOT w.r.t. x_n!).
One should use appropriate definition of degree (that is, w.r.t. x_0, ..., x_n)
in chinrem_gcd() too.
pgcd(): avoid infinite loop if the first GCD candidate coincides with GCD
136 if (H_lcoeff.is_equal(lc_gcd)) {
137 if ((Hprev-H).expand().smod(pn).is_zero()) // (*)
138 continue;
The check (*) can result in infinite loop if the (very) first GCD candidate
gives the correct GCD: any subsequent iterations give the same result, so
Hprev and H will be equal (hence the infinite loop). That check is not very
useful (AFAIR I was trying to avoid extra division checks), so let's remove it.
Richard Kreckel [Thu, 13 May 2010 16:30:40 +0000 (18:30 +0200)]
Explicit function disambiguation.
This is necessary for compilers where the hyperbolic and the tgamma function
templates are pulled in from <cmath> and compete with GiNaC's function
templates. GCC 4.4 and 4.5 need this, when compiling with -std=cxx0x.
Richard Kreckel [Thu, 13 May 2010 16:30:40 +0000 (18:30 +0200)]
Explicit function disambiguation.
This is necessary for compilers where the hyperbolic and the tgamma function
templates are pulled in from <cmath> and compete with GiNaC's function
templates. GCC 4.4 and 4.5 need this, when compiling with -std=cxx0x.
Richard Kreckel [Thu, 25 Mar 2010 22:08:54 +0000 (23:08 +0100)]
Really fixed the atan2(-Pi, 0) bug.
The problem was that atan2_eval assumed that if y is real and not
positive, it must be negative. But this neglects the fact that in
symbolic compution it may just not be possible to determine the
sign. Now, the expression is returned as it is. Ugly, but correct.
Richard Kreckel [Thu, 25 Mar 2010 22:08:54 +0000 (23:08 +0100)]
Really fixed the atan2(-Pi, 0) bug.
The problem was that atan2_eval assumed that if y is real and not
positive, it must be negative. But this neglects the fact that in
symbolic compution it may just not be possible to determine the
sign. Now, the expression is returned as it is. Ugly, but correct.
Jens Vollinga [Thu, 25 Mar 2010 09:36:41 +0000 (10:36 +0100)]
Fixed a bug in atan2. It gave a division by zero error for calls like
atan2(-Pi,0), because arguments like -Pi were not recognized (via
info_flags) as negative but as real nevertheless.
(cherry picked from commit 9e13d46552bb7852399867b9eb355732b9ded59e)
Jens Vollinga [Thu, 25 Mar 2010 09:36:41 +0000 (10:36 +0100)]
Fixed a bug in atan2. It gave a division by zero error for calls like
atan2(-Pi,0), because arguments like -Pi were not recognized (via
info_flags) as negative but as real nevertheless.
pgcd(): detect relatively prime polynomials properly...
... so pgcd() doesn't loop forever any more. Division test does not handle
relatively prime polynomials (because C = 1 divides any polynomial). So we
should stop interpolation (and return gcd of contents) if we got relatively
prime images (we should do that for efficiency reasons too).
pgcd(): detect relatively prime polynomials properly...
... so pgcd() doesn't loop forever any more. Division test does not handle
relatively prime polynomials (because C = 1 divides any polynomial). So we
should stop interpolation (and return gcd of contents) if we got relatively
prime images (we should do that for efficiency reasons too).
But the ability to do so is important for a lot of practical uses. So soon
after the C++98 standard was approved, a language defect report was filed
on this topic, see
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#195
The result is that compilers will be allowed to support reinterpret_cast
conversions of function pointers to other (pointers) types, and vice a versa.
Such conversions work with *current* compilers (GCC 4.x), but don't work
with older ones, hence this patch.