[GiNaC-list] Bug with evalm()?
Sheplyakov Alexei
varg at theor.jinr.ru
Fri Feb 9 19:46:43 CET 2007
Hello!
On Fri, Feb 09, 2007 at 05:39:50PM +0100, Martin Sandve Alnæs wrote:
> I believe there is a bug in the implementation of evalm().
> Its behaviour should be to do nothing if it is not applicable to
> the ex it is called on, right?
As of now, eval* methods do behave this way (well, mostly). [I'd
prefer them to throw an exception instead, so bugs in code become
evident earlier].
> The minimal example below throws an
> exception:
>
>
> #include <ginac/ginac.h>
>
> using namespace std;
> using namespace GiNaC;
>
> int main(int argc, char **argv)
> {
> ex x = symbol("x");
> ex e = sin(x);
> ex s = e.series(x == 0, 3);
> cout << "This will crash:" << endl;
Not exactly. This is an uncaught exception.
> ex m = s.evalm();
> return 0;
> }
>
>
> The error is:
>
> terminate called after throwing an instance of 'std::range_error'
> what(): basic::let_op(): pseries has no operands
> Aborted (core dumped)
This bug is unlikely to be fixed in GiNaC 1.3.X :( There are two
possible work-arounds:
1) catch std::range_error exception, e.g.
ex m;
try {
m = s.evalm();
} catch (std::range_error& oops) {
m = s;
}
This is not exactly correct (one might got std::range_error for some
"real" reason)...
2) convert the expression from power series to polynomial:
ex m = series_to_poly(s).evalm();
This one is not exaclty fool-proof: it will fail if s is not a power
series object...
> Of course, it doesn't make much sense to call evalm() on this
> expression, but it is a problem in an application where we want to
> call evalm() "just in case" on all ex objects that pass a certain
> point in the application.
I'd say that such an "just in a case" code is buggy and/or very
inefficient in first place.
> Thus a "do nothing" behaviour for evalm() is of great importance.
I agree -- at least it should be consistent with behaviour of
other eval* methods.
@ developers
The `pseries' class does not overload evalm(). So default basic::evalm()
is used, which needs let_op() or map(). But these are not overloaded
too, probably because semantics of such operations is not very clear.
Thus default basic::let_op() is used [which throws an exception]...
Here is a dumb fix:
[PATCH] pseries.{h, cpp}: provide no-op pseries::evalm()
Code like this:
symbol x;
ex test = sin(x).series(x, 5).evalm();
throws an exception. I'd say this is good, because it urges users
to fix their sloppy code. But this behaviour is inconsistent with one
of other eval* methods which are no-op if operation in question is
meaningless. Unfortunately this change is not suitable for GiNaC 1.3
due to the A[PB]I breakage.
---
ginac/pseries.cpp | 5 +++++
ginac/pseries.h | 1 +
2 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/ginac/pseries.cpp b/ginac/pseries.cpp
index db7cef3..a6780a6 100644
--- a/ginac/pseries.cpp
+++ b/ginac/pseries.cpp
@@ -464,6 +464,11 @@ ex pseries::imag_part() const
return (new pseries(var==point, v))->setflag(status_flags::dynallocated);
}
+ex pseries::evalm() const
+{
+ return *this;
+}
+
ex pseries::eval_integ() const
{
epvector *newseq = NULL;
diff --git a/ginac/pseries.h b/ginac/pseries.h
index ed266c4..e53baf6 100644
--- a/ginac/pseries.h
+++ b/ginac/pseries.h
@@ -59,6 +59,7 @@ public:
ex real_part() const;
ex imag_part() const;
ex eval_integ() const;
+ ex evalm() const;
protected:
ex derivative(const symbol & s) const;
--
1.4.4.4
Best regards,
Alexei
--
All science is either physics or stamp collecting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
Url : http://www.cebix.net/pipermail/ginac-list/attachments/20070209/5368c305/attachment.pgp
More information about the GiNaC-list
mailing list