Common evals method and its CWrappers #987

Merged
merged 17 commits into from Jun 22, 2016

Projects

None yet

5 participants

@rajithv
Contributor
rajithv commented Jun 14, 2016

No description provided.

@isuruf isuruf commented on an outdated diff Jun 14, 2016
symengine/eval.cpp
@@ -0,0 +1,24 @@
+#include<eval.h>
@isuruf
isuruf Jun 14, 2016 Member

symengine/eval.h

@isuruf isuruf commented on an outdated diff Jun 14, 2016
symengine/eval.cpp
@@ -0,0 +1,24 @@
+#include<eval.h>
+
+RCP<const Number> eval(const Basic &b, unsigned long bits = 53, bool real=False){
+ if (bits <= 53 && real) { //double
+ double d = eval_double(b);
@isuruf
isuruf Jun 14, 2016 Member

return a RealDouble here

@isuruf isuruf commented on an outdated diff Jun 14, 2016
symengine/eval.cpp
@@ -0,0 +1,24 @@
+#include<eval.h>
+
+RCP<const Number> eval(const Basic &b, unsigned long bits = 53, bool real=False){
+ if (bits <= 53 && real) { //double
+ double d = eval_double(b);
+ } else if (bits <= 53 && !real) { //complex double
+ std::complex<double> d = eval_complex_double(b);
@isuruf
isuruf Jun 14, 2016 Member

return a ComplexDouble here

@isuruf isuruf commented on an outdated diff Jun 14, 2016
symengine/eval.cpp
@@ -0,0 +1,24 @@
+#include<eval.h>
+
+RCP<const Number> eval(const Basic &b, unsigned long bits = 53, bool real=False){
+ if (bits <= 53 && real) { //double
+ double d = eval_double(b);
+ } else if (bits <= 53 && !real) { //complex double
+ std::complex<double> d = eval_complex_double(b);
+
+ } else if (bits >53 && real) { //mpfr
+ #ifdef HAVE_SYMENGINE_MPFR
+ mpfr_class mc = mpfr_class(bits);
+ mpfr_ptr result = mc.get_mpfr_t();
+ eval_mpfr(result, b, MPFR_RNDN);
+ return rcp(new RealMPFR(std::move(mc)));
@isuruf
isuruf Jun 14, 2016 Member

return make_rcp<RealMPFR>(std::move(mc));

@isuruf isuruf commented on an outdated diff Jun 14, 2016
symengine/eval.cpp
+ } else if (bits <= 53 && !real) { //complex double
+ std::complex<double> d = eval_complex_double(b);
+
+ } else if (bits >53 && real) { //mpfr
+ #ifdef HAVE_SYMENGINE_MPFR
+ mpfr_class mc = mpfr_class(bits);
+ mpfr_ptr result = mc.get_mpfr_t();
+ eval_mpfr(result, b, MPFR_RNDN);
+ return rcp(new RealMPFR(std::move(mc)));
+ #endif //HAVE_SYMENGINE_MPFR
+ } else { //mpc
+ #ifdef HAVE_SYMENGINE_MPC
+ mpc_class mc = mpc_class(bits);
+ mpc_ptr result = mc.get_mpc_t();
+ eval_mpc(result, b, MPFR_RNDN);
+ return rcp(new RealMPC(std::move(mc)));
@isuruf
isuruf Jun 14, 2016 Member

return make_rcp<ComplexMPC>(std::move(mc));

@rajithv rajithv Init eval cpp code
c1e62d0
@isuruf isuruf commented on an outdated diff Jun 14, 2016
symengine/eval.cpp
+#endif // SYMENGINE_HAVE_MPFR
+
+#ifdef SYMENGINE_HAVE_MPC
+#include <mpc.h>
+#include <symengine/complex_mpc.h>
+#include <symengine/eval_mpc.h>
+#endif // SYMENGINE_HAVE_MPC
+
+namespace SymEngine
+{
+
+RCP<const Number> eval(const Basic &b, unsigned long bits, bool real)
+{
+ if (bits <= 53 && real) { // double
+ double d = eval_double(b);
+ return make_rcp<RealDouble>(std::move(d));
@isuruf
isuruf Jun 14, 2016 Member

You can do, return real_double(d);

@isuruf isuruf commented on an outdated diff Jun 14, 2016
symengine/eval.cpp
+#include <mpc.h>
+#include <symengine/complex_mpc.h>
+#include <symengine/eval_mpc.h>
+#endif // SYMENGINE_HAVE_MPC
+
+namespace SymEngine
+{
+
+RCP<const Number> eval(const Basic &b, unsigned long bits, bool real)
+{
+ if (bits <= 53 && real) { // double
+ double d = eval_double(b);
+ return make_rcp<RealDouble>(std::move(d));
+ } else if (bits <= 53 && !real) { // complex double
+ std::complex<double> d = eval_complex_double(b);
+ return make_rcp<ComplexDouble>(std::move(d));
@isuruf
isuruf Jun 14, 2016 Member

return complex_double(d);

@isuruf isuruf commented on an outdated diff Jun 14, 2016
symengine/eval.cpp
+
+RCP<const Number> eval(const Basic &b, unsigned long bits, bool real)
+{
+ if (bits <= 53 && real) { // double
+ double d = eval_double(b);
+ return make_rcp<RealDouble>(std::move(d));
+ } else if (bits <= 53 && !real) { // complex double
+ std::complex<double> d = eval_complex_double(b);
+ return make_rcp<ComplexDouble>(std::move(d));
+ } else if (bits > 53 && real) { // mpfr
+#ifdef HAVE_SYMENGINE_MPFR
+ mpfr_class mc = mpfr_class(bits);
+ mpfr_ptr result = mc.get_mpfr_t();
+ eval_mpfr(result, b, MPFR_RNDN);
+ return make_rcp<RealMPFR>(std::move(mc));
+#endif // HAVE_SYMENGINE_MPFR
@isuruf
isuruf Jun 14, 2016 Member

throw an error here if HAVE_SYMENGINE_MPFR is not defined saying something like, https://github.com/symengine/symengine.py/blob/master/symengine/lib/symengine_wrapper.pyx#L2111

@isuruf isuruf commented on the diff Jun 14, 2016
symengine/eval.cpp
+ } else if (bits <= 53 && !real) { // complex double
+ std::complex<double> d = eval_complex_double(b);
+ return make_rcp<ComplexDouble>(std::move(d));
+ } else if (bits > 53 && real) { // mpfr
+#ifdef HAVE_SYMENGINE_MPFR
+ mpfr_class mc = mpfr_class(bits);
+ mpfr_ptr result = mc.get_mpfr_t();
+ eval_mpfr(result, b, MPFR_RNDN);
+ return make_rcp<RealMPFR>(std::move(mc));
+#endif // HAVE_SYMENGINE_MPFR
+ } else { // mpc
+#ifdef HAVE_SYMENGINE_MPC
+ mpc_class mc = mpc_class(bits);
+ mpc_ptr result = mc.get_mpc_t();
+ eval_mpc(result, b, MPFR_RNDN);
+ return make_rcp<ComplexMPC>(std::move(mc));
@isuruf
isuruf Jun 14, 2016 Member

Same here

rajithv added some commits Jun 14, 2016
@rajithv rajithv Fixing errors in eval.h and eval.cpp
affb2c9
@rajithv rajithv cwrapper for eval started
7d8a617
@rajithv rajithv Fixed error with includes
fbf5dba
@rajithv rajithv Exceptions for missing MPFR and MPC
7abea89
@rajithv rajithv Adding tests to eval and eval cwrapper
d4ce540
@abinashmeher999 abinashmeher999 commented on an outdated diff Jun 15, 2016
symengine/tests/cwrapper/test_cwrapper.c
@@ -798,6 +798,25 @@ void test_ntheory() {
basic_free_stack(i5);
}
+void test_eval(){
+ basic sin2;
+ basic_new_stack(sin2);
+ str *s;
+
+ integer_set_si(sin2, 2);
+ basic_sin(sin2, sin2);
+ basic_eval(sin2, sin2, 53, 1);
+ basic_str(s, sin2);
+ SYMENGINE_C_ASSERT(basic_get_type(x) == SYMENGINE_REAL_DOUBLE);
+ double d = 0.90929742682;
+ double d2 = real_double_get_d(sin2);
+
+ SYMENGINE_C_ASSERT( fabs(d - d2) < 0.0000000001 );
@abinashmeher999
abinashmeher999 Jun 15, 2016 Contributor

@rajithv d has 11 digits after the decimal, so shouldn't the difference also be compared against 0.00000000001(11 digits after decimal`)?

@rajithv rajithv cwrapper for real_mpfr is_zero method
7c84b0a
@certik
Contributor
certik commented Jun 16, 2016

I think that this looks good, but I wouldn't call it eval but evalf, like in SymPy, e.g. a floating point evaluation.

rajithv added some commits Jun 17, 2016
@rajithv rajithv Tests for eval under real_mpfr, real_double and complex_double condit…
…ions
93cc8cb
@rajithv rajithv Cwrapper tests for MPC and name change eval -> evalf
99cef42
@rajithv rajithv Merge branch 'master' of https://github.com/symengine/symengine into …
…evals
fb562f6
@rajithv rajithv Fixing mpfr cwrapper tests
43277fa
@rajithv rajithv C++ tests added
f2fdd43
@rajithv rajithv changed the title from [WIP] Common evals method and its CWrappers to Common evals method and its CWrappers Jun 19, 2016
@Sumith1896
Member

@rajithv Could you have a look at the tests? There seems to be a segfault

rajithv added some commits Jun 19, 2016
@rajithv rajithv Trying to fix tests 36a09ea
@rajithv rajithv Merge branch 'master' of https://github.com/symengine/symengine into …
…evals
ebb9993
@rajithv
Contributor
rajithv commented Jun 20, 2016

The tests are passing. :)
Ready for review.
@isuruf @abinashmeher999

@isuruf
Member
isuruf commented Jun 20, 2016

Can you format with clang-format?

@abinashmeher999 abinashmeher999 commented on an outdated diff Jun 20, 2016
symengine/tests/eval/test_evalf.cpp
+#endif // HAVE_SYMENGINE_MPFR
+
+TEST_CASE("evalf: complex_double", "[evalf]")
+{
+ RCP<const Basic> r1, r2;
+ r1 = add(sin(integer(4)), mul(sin(integer(3)), I));
+ // r1 = sin(4) + sin(3)i
+ r2 = add(sin(integer(2)), mul(sin(integer(7)), I));
+ // r2 = sin(2) + sin(7)i
+
+ r1 = mul(r1, r2);
+ // r1 = (sin(4) + sin(3)i) * (sin(2) + sin(7)i)
+
+ r2 = evalf(*r1, 53, false);
+ // SYMENGINE_COMPLEX_DOUBLE = 3
+ REQUIRE(r2->get_type_code() == 3);
@abinashmeher999
abinashmeher999 Jun 20, 2016 Contributor

Try to use the actual enums(I am sure there should be a way) everywhere you have written like this, because if any new types are added in between these tests will fail.

@abinashmeher999 abinashmeher999 commented on the diff Jun 20, 2016
symengine/tests/eval/test_evalf.cpp
+ // SYMENGINE_REAL_MPFR = 4
+ REQUIRE(r2->get_type_code() == 4);
+ REQUIRE((rcp_static_cast<const RealMPFR>(r2))->is_zero());
+}
+#endif // HAVE_SYMENGINE_MPFR
+
+TEST_CASE("evalf: complex_double", "[evalf]")
+{
+ RCP<const Basic> r1, r2;
+ r1 = add(sin(integer(4)), mul(sin(integer(3)), I));
+ // r1 = sin(4) + sin(3)i
+ r2 = add(sin(integer(2)), mul(sin(integer(7)), I));
+ // r2 = sin(2) + sin(7)i
+
+ r1 = mul(r1, r2);
+ // r1 = (sin(4) + sin(3)i) * (sin(2) + sin(7)i)
@abinashmeher999
abinashmeher999 Jun 20, 2016 Contributor

I like comments like these. Makes reading easier. :)

@abinashmeher999 abinashmeher999 commented on an outdated diff Jun 20, 2016
symengine/tests/cwrapper/test_cwrapper.c
+ basic_add(n2, n2, temp);
+ // n2 = sin(2) + sin(7)i
+
+ basic_mul(n1, n1, n2);
+ // n1 = (sin(4) + sin(3)i) * (sin(2) + sin(7)i)
+
+ basic_evalf(eval, n1, 53, 0);
+ SYMENGINE_C_ASSERT(basic_get_type(eval) == SYMENGINE_COMPLEX_DOUBLE);
+ d = -0.780872515;
+ complex_double_real_part(temp, eval);
+ d2 = real_double_get_d(temp);
+ complex_double_imaginary_part(temp, eval);
+ double d3 = real_double_get_d(temp);
+ double d4 = -0.3688890370;
+ d = fabs(d-d2);
+ d4 = fabs(d4 - d3);
@abinashmeher999
abinashmeher999 Jun 20, 2016 Contributor

Inconsistent style

@abinashmeher999 abinashmeher999 commented on an outdated diff Jun 20, 2016
symengine/tests/cwrapper/test_cwrapper.c
+ // n1 = (sin(4) + sin(3)i) * (sin(2) + sin(7)i)
+
+ basic_evalf(eval, n1, 53, 0);
+ SYMENGINE_C_ASSERT(basic_get_type(eval) == SYMENGINE_COMPLEX_DOUBLE);
+ d = -0.780872515;
+ complex_double_real_part(temp, eval);
+ d2 = real_double_get_d(temp);
+ complex_double_imaginary_part(temp, eval);
+ double d3 = real_double_get_d(temp);
+ double d4 = -0.3688890370;
+ d = fabs(d-d2);
+ d4 = fabs(d4 - d3);
+
+ d2 = 0.000001;
+
+ SYMENGINE_C_ASSERT( d < d2 && d4 < d2);
@abinashmeher999
abinashmeher999 Jun 20, 2016 Contributor

Same here. Please run clang-format.

@abinashmeher999 abinashmeher999 commented on the diff Jun 20, 2016
symengine/eval.cpp
@@ -0,0 +1,52 @@
+#include <exception>
+#include <symengine/eval.h>
+#include <symengine/eval_double.h>
+#include <symengine/real_double.h>
+#include <symengine/complex_double.h>
+#include <symengine/symengine_rcp.h>
+#ifdef HAVE_SYMENGINE_MPFR
+#include <mpfr.h>
+#include <symengine/real_mpfr.h>
+#include <symengine/eval_mpfr.h>
+#endif // HAVE_SYMENGINE_MPFR
+
+#ifdef HAVE_SYMENGINE_MPC
+#include <mpc.h>
@abinashmeher999
abinashmeher999 Jun 20, 2016 Contributor

<mpc.h> is already there in <symengine/complex_mpc.h>. I am not sure if occurrences like these are removed.

@isuruf isuruf and 1 other commented on an outdated diff Jun 20, 2016
symengine/tests/eval/test_evalf.cpp
+ // r1 = (sin(4) + sin(3)i) * (sin(2) + sin(7)i)
+
+ r2 = evalf(*r1, 53, false);
+ // SYMENGINE_COMPLEX_DOUBLE = 3
+ REQUIRE(r2->get_type_code() == 3);
+
+ double d1 = (rcp_static_cast<const RealDouble>(
+ (rcp_static_cast<const ComplexDouble>(r2))->real_part()))
+ ->as_double();
+ double d2 = -0.780872515;
+ d2 = fabs(d1 - d2);
+ d1 = 0.000001;
+ REQUIRE(d2 < d1);
+
+ d1 = (rcp_static_cast<const RealDouble>(
+ (rcp_static_cast<const ComplexDouble>(r2))->imaginary_part()))
@isuruf
isuruf Jun 20, 2016 Member

Add asserts above to make sure r2 is a ComplexDouble and the imaginary part is a RealDouble.

@rajithv
rajithv Jun 20, 2016 Contributor

assertion for r2 is done on line no. 136
and as for imaginary part, isn't it guaranteed to return a RealDouble, when obtaining the imaginary_part from a ComplexDouble?

@isuruf
isuruf Jun 21, 2016 Member

Sorry, I didn't see Line 136 assert.
Btw, you should check imaginary_part is a ReaDouble even if you are sure that it is the case.

@isuruf isuruf commented on an outdated diff Jun 20, 2016
symengine/tests/eval/test_evalf.cpp
+}
+
+#ifdef HAVE_SYMENGINE_MPC
+TEST_CASE("evalf: complex_mpc", "[evalf]")
+{
+ RCP<const Basic> r1, r2, c1, c2;
+ r1 = mul(pi, integer(integer_class("1963319607")));
+ r2 = integer(integer_class("6167950454"));
+ c1 = add(r1, mul(r1, I));
+ c2 = add(r2, mul(r2, I));
+
+ r1 = evalf(*c1, 100, false);
+
+ // SYMENGINE_COMPLEX_MPC = 5
+ REQUIRE(r1->get_type_code() == 5);
+ REQUIRE(!(rcp_static_cast<const ComplexMPC>(r1))->is_zero());
@isuruf
isuruf Jun 20, 2016 Member

Same here

@isuruf isuruf commented on an outdated diff Jun 20, 2016
symengine/tests/eval/test_evalf.cpp
+using SymEngine::vec_basic;
+using SymEngine::rational_class;
+using SymEngine::max;
+using SymEngine::min;
+using SymEngine::min;
+using SymEngine::rcp_static_cast;
+
+TEST_CASE("evalf: real_double", "[evalf]")
+{
+ RCP<const Basic> r1, r2;
+ r1 = sin(integer(2));
+ r2 = evalf(*r1, 53, true);
+ // SYMENGINE_REAL_DOUBLE = 6
+ REQUIRE(r2->get_type_code() == 6);
+ double d1 = 0.909297;
+ double d2 = (rcp_static_cast<const RealDouble>(r2))->as_double();
@isuruf
isuruf Jun 20, 2016 Member

Same here

rajithv added some commits Jun 20, 2016
@rajithv rajithv formatted using clang-format-3.7 a8fd30e
@rajithv rajithv Adding Enums
9de8231
@isuruf isuruf commented on an outdated diff Jun 21, 2016
symengine/tests/eval/test_evalf.cpp
+}
+#endif // HAVE_SYMENGINE_MPFR
+
+TEST_CASE("evalf: complex_double", "[evalf]")
+{
+ RCP<const Basic> r1, r2;
+ r1 = add(sin(integer(4)), mul(sin(integer(3)), I));
+ // r1 = sin(4) + sin(3)i
+ r2 = add(sin(integer(2)), mul(sin(integer(7)), I));
+ // r2 = sin(2) + sin(7)i
+
+ r1 = mul(r1, r2);
+ // r1 = (sin(4) + sin(3)i) * (sin(2) + sin(7)i)
+
+ r2 = evalf(*r1, 53, false);
+ REQUIRE(static_cast<SymEngine::TypeID>(r2->get_type_code())
@isuruf
isuruf Jun 21, 2016 Member

Is this static_cast<SymEngine::TypeID> really needed?

@rajithv rajithv Added assertions for real and imaginary
5f7bb63
@isuruf isuruf merged commit 59e17e3 into symengine:master Jun 22, 2016

4 checks passed

codecov/patch 91.66% of diff hit (target 68.45%)
Details
codecov/project 68.81% (+0.36%) compared to a605e4b
Details
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@certik
Contributor
certik commented Jun 27, 2016

Thanks @rajithv and @isuruf.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment