eval.cpp
1 #include <exception>
2 #include <symengine/eval.h>
4 #include <symengine/real_double.h>
5 #include <symengine/complex_double.h>
6 #include <symengine/symengine_rcp.h>
7 #include <symengine/visitor.h>
8 #ifdef HAVE_SYMENGINE_MPFR
9 #include <mpfr.h>
10 #include <symengine/real_mpfr.h>
11 #include <symengine/eval_mpfr.h>
12 #endif // HAVE_SYMENGINE_MPFR
13 
14 #ifdef HAVE_SYMENGINE_MPC
15 #include <mpc.h>
16 #include <symengine/complex_mpc.h>
17 #include <symengine/eval_mpc.h>
18 #endif // HAVE_SYMENGINE_MPC
19 
20 namespace SymEngine
21 {
22 
23 RCP<const Number> evalf_numeric(const Basic &b, unsigned long bits, bool real)
24 {
25  if (bits <= 53 && real) { // double
26  double d = eval_double(b);
27  return real_double(d);
28  } else if (bits <= 53 && !real) { // complex double
29  std::complex<double> d = eval_complex_double(b);
30  return complex_double(d);
31  } else if (bits > 53 && real) { // mpfr
32 #ifdef HAVE_SYMENGINE_MPFR
33  mpfr_class mc = mpfr_class(bits);
34  mpfr_ptr result = mc.get_mpfr_t();
35  eval_mpfr(result, b, MPFR_RNDN);
36  return make_rcp<RealMPFR>(std::move(mc));
37 #else
39  "For multiple bit precision, MPFR is needed");
40 #endif // HAVE_SYMENGINE_MPFR
41  } else { // mpc
42 #ifdef HAVE_SYMENGINE_MPC
43  mpc_class mc = mpc_class(bits);
44  mpc_ptr result = mc.get_mpc_t();
45  eval_mpc(result, b, MPFR_RNDN);
46  return make_rcp<ComplexMPC>(std::move(mc));
47 #else
49  "For multiple bit precision, MPC is needed");
50 #endif // HAVE_SYMENGINE_MPC
51  }
52 }
53 
54 class EvalVisitor : public BaseVisitor<EvalVisitor, TransformVisitor>
55 {
56 protected:
57  unsigned long bits;
58 
59 public:
60  EvalVisitor(unsigned long bits) : bits(bits) {}
61  using TransformVisitor::apply;
62  using TransformVisitor::bvisit;
63  void bvisit(const Number &x)
64  {
65  result_ = evalf_numeric(x, bits, true);
66  }
67  void bvisit(const ComplexBase &x)
68  {
69  result_ = evalf_numeric(x, bits, false);
70  }
71  void bvisit(const Constant &x)
72  {
73  result_ = evalf_numeric(x, bits, true);
74  }
75  void bvisit(const NumberWrapper &x)
76  {
77  result_ = x.eval(bits)->rcp_from_this();
78  }
79  void bvisit(const FunctionWrapper &x)
80  {
81  result_ = x.eval(bits)->rcp_from_this();
82  }
83 };
84 
85 RCP<const Basic> evalf(const Basic &b, unsigned long bits, EvalfDomain domain)
86 {
87 #ifndef HAVE_SYMENGINE_MPFR
88  if (bits > 53) {
90  "For multiple bit precision, MPFR is needed");
91  }
92 #endif
93 #ifndef HAVE_SYMENGINE_MPC
94  if (bits > 53 and domain == EvalfDomain::Complex) {
96  "For multiple bit precision, MPC is needed");
97  }
98 #endif
99  if (domain == EvalfDomain::Real) {
100  return evalf_numeric(b, bits, true);
101  } else if (domain == EvalfDomain::Complex) {
102  return evalf_numeric(b, bits, false);
103  }
104 
105  EvalVisitor v(bits);
106  return v.apply(b.rcp_from_this());
107 }
108 
109 } // namespace SymEngine
The lowest unit of symbolic representation.
Definition: basic.h:97
ComplexBase Class for deriving all complex classes.
Definition: complex.h:16
RCP< T > rcp_from_this()
Get RCP<T> pointer to self (it will cast the pointer to T)
T move(T... args)
Main namespace for SymEngine package.
Definition: add.cpp:19