Skip to content
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

Merged
merged 9 commits into from Jan 22, 2017

Conversation

ShikharJ
Copy link
Member

@ShikharJ ShikharJ commented Jan 19, 2017

@isuruf I'am not confident that this is the expected implementation. Please review and suggest improvements.
Fixes #1174

@@ -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)) {
Copy link
Contributor

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.

Copy link
Member Author

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.

Copy link
Contributor

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)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here?

@jppelteret
Copy link
Contributor

@ShikharJ By the way, if you write fixes #1174 in your initial commit message then the corresponding issue is automatically closed when the PR is merged 😀

@isuruf
Copy link
Member

isuruf commented Jan 19, 2017

@ShikharJ, this should be handled in a more generic way. If you don't mind, I'll push some changes to this PR.

@ShikharJ
Copy link
Member Author

@isuruf Sure.

@jppelteret
Copy link
Contributor

Thanks again to you both for working on this issue so quickly!


#ifdef HAVE_SYMENGINE_MPFR

using SymEngine::eval_mpfr;

Copy link
Member

@isuruf isuruf Jan 19, 2017

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

@ShikharJ ShikharJ force-pushed the Issue1174 branch 2 times, most recently from 00b226e to f68320d Compare January 21, 2017 16:08
@ShikharJ
Copy link
Member Author

@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},
Copy link
Member

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

Copy link
Member Author

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?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

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?

Copy link
Member

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.

Copy link
Contributor

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!

Copy link
Member

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()) {
Copy link
Contributor

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?

Copy link
Member Author

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.

Copy link
Member

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.

Copy link
Contributor

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()) {
Copy link
Contributor

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...

@ShikharJ ShikharJ force-pushed the Issue1174 branch 2 times, most recently from 95108bb to d7b5258 Compare January 21, 2017 17:51
@ShikharJ
Copy link
Member Author

ping @isuruf @jppelteret

@jppelteret
Copy link
Contributor

Awesome. Looks good to me!

@isuruf isuruf merged commit c1cd1ad into symengine:master Jan 22, 2017
@ShikharJ ShikharJ deleted the Issue1174 branch January 22, 2017 16:48
ranjithkumar007 pushed a commit to ranjithkumar007/symengine that referenced this pull request Jan 31, 2017
Automatic Evaluation of pow(RealDouble, Constant)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants