New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Automatic Evaluation of pow(RealDouble, Constant) #1177
Conversation
@@ -161,6 +163,14 @@ RCP<const Basic> pow(const RCP<const Basic> &a, const RCP<const Basic> &b) | |||
.pow(*rcp_static_cast<const Number>(b)); | |||
} | |||
} | |||
if (is_a<RealDouble>(*a) and is_a<Constant>(*b)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Surely this should be a Number
instead of a RealDouble
? This would cater for the case where a
is complex, derives from NumberWrapper
etc. If so, then I'm guessing that one should likely call a.pow(eval_double(*b))
or similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jppelteret eval_double(*b)
returns a plain double
, which I think is not overloaded in the pow
functions of classNumber
or Complex
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, fair enough. Alternatively one could then do a.pow(real_double(*b))
.
return number( | ||
std::pow(down_cast<const RealDouble &>(*a).i, eval_double(*b))); | ||
} | ||
if (is_a<Constant>(*a) and is_a<RealDouble>(*b)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here?
@ShikharJ By the way, if you write |
@ShikharJ, this should be handled in a more generic way. If you don't mind, I'll push some changes to this PR. |
@isuruf Sure. |
Thanks again to you both for working on this issue so quickly! |
|
||
#ifdef HAVE_SYMENGINE_MPFR | ||
|
||
using SymEngine::eval_mpfr; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need the above 2 lines
Here Number should be an inexact number. Also added pow(Number, Constant)
00b226e
to
f68320d
Compare
@isuruf @jppelteret The code coverage is passable as of now. Can you please take a glance and through and suggest improvements if necessary? |
@@ -107,6 +107,8 @@ TEST_CASE("eval_double: eval_double", "[eval_double]") | |||
{SymEngine::atan2(r1, neg(r2)), 2.08867384922582}, | |||
{mul(pi, mul(E, EulerGamma)), 4.92926836742289}, | |||
{pow(mul(EulerGamma, r4), integer(8)), 4813.54354505117582}, | |||
{pow(E, real_double(0.2)), 1.22140275816017}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test checks that whatever the result of pow(E, real_double(0.2))
can be evaluated. What this PR does is evaluating pow(E, real_double(0.2))
automatically without the need of evaluation using eval_double
and the like. Can you add a test to check that pow(E, real_double(0.2))
is a RealDouble
and that it's value is close to 1.22140275816017
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@isuruf In which test-file would that test be the most appropiate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See this test, https://github.com/symengine/symengine/blob/master/symengine/tests/basic/test_arit.cpp#L761-L769
You can have a new test over there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks very much for including some tests! If its appropriate, may you please also check that this works if the base or exponent is a Symbol
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jppelteret, what do you mean by that? E**2.0
will get evaluated while x**2.0
will not be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@isuruf I was think of the case E**x
and x**E
and subsequent substitution. But as I said, if I've misunderstood what's being tested then my comment should of course be ignored!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. That's a good test.
@ShikharJ, can you add that as well?
exp(x)->subs({{x, 1.0}})
is a RealDouble and the value is close to 2.71828182845905
.pow(*rcp_static_cast<const Number>(b)); | ||
} else if (is_a<Constant>(*a)) { | ||
RCP<const Number> p = rcp_static_cast<const Number>(b); | ||
if (not p->is_exact()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if this condition is not met?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jppelteret The function will return make_rcp<const Pow>(a, b);
. Basically, it will be printed as it is, no numeric evaluation would be done. not p->is_exact()
statement holds true for RealDouble
and similar classes, as a double is never exact. @isuruf Please correct me if I am mistaken.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, E**2
is not evaluated automatically, but E**2.0
is evaluated automatically in the same sense that sin(2)
is not evaluated automatically, but sin(2.0)
is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yes, you must be right. I didn't notice the default condition at the end of the function :-) Thanks!
if (is_a<Constant>(*b) and is_a_Number(*a)) { | ||
// Handle 2.0**E | ||
RCP<const Number> p = rcp_static_cast<const Number>(a); | ||
if (not p->is_exact()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And ditto for this condition...
95108bb
to
d7b5258
Compare
ping @isuruf @jppelteret |
Awesome. Looks good to me! |
Automatic Evaluation of pow(RealDouble, Constant)
@isuruf I'am not confident that this is the expected implementation. Please review and suggest improvements.
Fixes #1174