eval_double.cpp
1 #include <symengine/visitor.h>
3 #include <symengine/symengine_exception.h>
4 
5 namespace SymEngine
6 {
7 
8 template <typename T, typename C>
9 class EvalDoubleVisitor : public BaseVisitor<C>
10 {
11 protected:
12  /*
13  The 'result_' variable is assigned into at the very end of each visit()
14  methods below. The only place where these methods are called from is the
15  line 'b.accept(*this)' in apply() and the 'result_' is immediately
16  returned. Thus no corruption can happen and apply() can be safely called
17  recursively.
18  */
19  T result_;
20 
21 public:
22  T apply(const Basic &b)
23  {
24  b.accept(*down_cast<C *>(this));
25  return result_;
26  }
27 
28  void bvisit(const Integer &x)
29  {
30  T tmp = mp_get_d(x.as_integer_class());
31  result_ = tmp;
32  }
33 
34  void bvisit(const Rational &x)
35  {
36  T tmp = mp_get_d(x.as_rational_class());
37  result_ = tmp;
38  }
39 
40  void bvisit(const RealDouble &x)
41  {
42  T tmp = x.i;
43  result_ = tmp;
44  }
45 #ifdef HAVE_SYMENGINE_MPFR
46  void bvisit(const RealMPFR &x)
47  {
48  T tmp = mpfr_get_d(x.i.get_mpfr_t(), MPFR_RNDN);
49  result_ = tmp;
50  }
51 #endif
52  void bvisit(const Add &x)
53  {
54  T tmp = 0;
55  for (const auto &p : x.get_args())
56  tmp += apply(*p);
57  result_ = tmp;
58  }
59 
60  void bvisit(const Mul &x)
61  {
62  T tmp = 1;
63  for (const auto &p : x.get_args())
64  tmp *= apply(*p);
65  result_ = tmp;
66  }
67 
68  void bvisit(const Pow &x)
69  {
70  T exp_ = apply(*(x.get_exp()));
71  if (eq(*(x.get_base()), *E)) {
72  result_ = std::exp(exp_);
73  } else {
74  T base_ = apply(*(x.get_base()));
75  result_ = std::pow(base_, exp_);
76  }
77  }
78 
79  void bvisit(const Sin &x)
80  {
81  T tmp = apply(*(x.get_arg()));
82  result_ = std::sin(tmp);
83  }
84 
85  void bvisit(const Cos &x)
86  {
87  T tmp = apply(*(x.get_arg()));
88  result_ = std::cos(tmp);
89  }
90 
91  void bvisit(const Tan &x)
92  {
93  T tmp = apply(*(x.get_arg()));
94  result_ = std::tan(tmp);
95  }
96 
97  void bvisit(const Symbol &)
98  {
99  throw SymEngineException("Symbol cannot be evaluated.");
100  };
101 
102  void bvisit(const Log &x)
103  {
104  T tmp = apply(*(x.get_arg()));
105  result_ = std::log(tmp);
106  };
107 
108  void bvisit(const Cot &x)
109  {
110  T tmp = apply(*(x.get_arg()));
111  result_ = 1.0 / std::tan(tmp);
112  };
113 
114  void bvisit(const Csc &x)
115  {
116  T tmp = apply(*(x.get_arg()));
117  result_ = 1.0 / std::sin(tmp);
118  };
119 
120  void bvisit(const Sec &x)
121  {
122  T tmp = apply(*(x.get_arg()));
123  result_ = 1.0 / std::cos(tmp);
124  };
125 
126  void bvisit(const ASin &x)
127  {
128  T tmp = apply(*(x.get_arg()));
129  result_ = std::asin(tmp);
130  };
131 
132  void bvisit(const ACos &x)
133  {
134  T tmp = apply(*(x.get_arg()));
135  result_ = std::acos(tmp);
136  };
137 
138  void bvisit(const ASec &x)
139  {
140  T tmp = apply(*(x.get_arg()));
141  result_ = std::acos(1.0 / tmp);
142  };
143 
144  void bvisit(const ACsc &x)
145  {
146  T tmp = apply(*(x.get_arg()));
147  result_ = std::asin(1.0 / tmp);
148  };
149 
150  void bvisit(const ATan &x)
151  {
152  T tmp = apply(*(x.get_arg()));
153  result_ = std::atan(tmp);
154  };
155 
156  void bvisit(const ACot &x)
157  {
158  T tmp = apply(*(x.get_arg()));
159  result_ = std::atan(1.0 / tmp);
160  };
161 
162  void bvisit(const Sinh &x)
163  {
164  T tmp = apply(*(x.get_arg()));
165  result_ = std::sinh(tmp);
166  };
167 
168  void bvisit(const Csch &x)
169  {
170  T tmp = apply(*(x.get_arg()));
171  result_ = 1.0 / std::sinh(tmp);
172  };
173 
174  void bvisit(const Cosh &x)
175  {
176  T tmp = apply(*(x.get_arg()));
177  result_ = std::cosh(tmp);
178  };
179 
180  void bvisit(const Sech &x)
181  {
182  T tmp = apply(*(x.get_arg()));
183  result_ = 1.0 / std::cosh(tmp);
184  };
185 
186  void bvisit(const Tanh &x)
187  {
188  T tmp = apply(*(x.get_arg()));
189  result_ = std::tanh(tmp);
190  };
191 
192  void bvisit(const Coth &x)
193  {
194  T tmp = apply(*(x.get_arg()));
195  result_ = 1.0 / std::tanh(tmp);
196  };
197 
198  void bvisit(const ASinh &x)
199  {
200  T tmp = apply(*(x.get_arg()));
201  result_ = std::asinh(tmp);
202  };
203 
204  void bvisit(const ACsch &x)
205  {
206  T tmp = apply(*(x.get_arg()));
207  result_ = std::asinh(1.0 / tmp);
208  };
209 
210  void bvisit(const ACosh &x)
211  {
212  T tmp = apply(*(x.get_arg()));
213  result_ = std::acosh(tmp);
214  };
215 
216  void bvisit(const ATanh &x)
217  {
218  T tmp = apply(*(x.get_arg()));
219  result_ = std::atanh(tmp);
220  };
221 
222  void bvisit(const ACoth &x)
223  {
224  T tmp = apply(*(x.get_arg()));
225  result_ = std::atanh(1.0 / tmp);
226  };
227 
228  void bvisit(const ASech &x)
229  {
230  T tmp = apply(*(x.get_arg()));
231  result_ = std::acosh(1.0 / tmp);
232  };
233 
234  void bvisit(const Constant &x)
235  {
236  if (eq(x, *pi)) {
237  result_ = std::atan2(0, -1);
238  } else if (eq(x, *E)) {
239  result_ = std::exp(1);
240  } else if (eq(x, *EulerGamma)) {
241  result_ = 0.5772156649015328606065; // use until polygamma or
242  // digamma is implemented
243  } else if (eq(x, *Catalan)) {
244  result_ = 0.9159655941772190150546;
245  } else if (eq(x, *GoldenRatio)) {
246  result_ = 1.6180339887498948482045;
247  } else {
248  throw NotImplementedError("Constant " + x.get_name()
249  + " is not implemented.");
250  }
251  };
252 
253  void bvisit(const Abs &x)
254  {
255  T tmp = apply(*(x.get_arg()));
256  result_ = std::abs(tmp);
257  };
258 
259  void bvisit(const Basic &)
260  {
261  throw NotImplementedError("Not Implemented");
262  };
263 
264  void bvisit(const NumberWrapper &x)
265  {
266  apply(*(x.eval(53)));
267  }
268 
269  void bvisit(const FunctionWrapper &x)
270  {
271  apply(*(x.eval(53)));
272  }
273 
274  void bvisit(const UnevaluatedExpr &x)
275  {
276  apply(*x.get_arg());
277  }
278 };
279 
280 template <typename C>
281 class EvalRealDoubleVisitor : public EvalDoubleVisitor<double, C>
282 {
283 public:
284  // Classes not implemented are
285  // Subs, UpperGamma, LowerGamma, Dirichlet_eta, Zeta
286  // LeviCivita, KroneckerDelta, LambertW
287  // Derivative, Complex, ComplexDouble, ComplexMPC
288 
292 
293  void bvisit(const ATan2 &x)
294  {
295  double num = apply(*(x.get_num()));
296  double den = apply(*(x.get_den()));
297  result_ = std::atan2(num, den);
298  };
299 
300  void bvisit(const Gamma &x)
301  {
302  double tmp = apply(*(x.get_args()[0]));
303  result_ = std::tgamma(tmp);
304  };
305 
306  void bvisit(const LogGamma &x)
307  {
308  double tmp = apply(*(x.get_args()[0]));
309  result_ = std::lgamma(tmp);
310  }
311 
312  void bvisit(const Erf &x)
313  {
314  double tmp = apply(*(x.get_args()[0]));
315  result_ = std::erf(tmp);
316  }
317 
318  void bvisit(const Erfc &x)
319  {
320  double tmp = apply(*(x.get_args()[0]));
321  result_ = std::erfc(tmp);
322  }
323 
324  void bvisit(const Equality &x)
325  {
326  double lhs_ = apply(*(x.get_arg1()));
327  double rhs_ = apply(*(x.get_arg2()));
328  result_ = (lhs_ == rhs_);
329  }
330 
331  void bvisit(const Unequality &x)
332  {
333  double lhs_ = apply(*(x.get_arg1()));
334  double rhs_ = apply(*(x.get_arg2()));
335  result_ = (lhs_ != rhs_);
336  }
337 
338  void bvisit(const LessThan &x)
339  {
340  double lhs_ = apply(*(x.get_arg1()));
341  double rhs_ = apply(*(x.get_arg2()));
342  result_ = (lhs_ <= rhs_);
343  }
344 
345  void bvisit(const StrictLessThan &x)
346  {
347  double lhs_ = apply(*(x.get_arg1()));
348  double rhs_ = apply(*(x.get_arg2()));
349  result_ = (lhs_ < rhs_);
350  }
351 
352  void bvisit(const Max &x)
353  {
354  auto d = x.get_args();
355  auto p = d.begin();
356  double result = apply(*(*p));
357  p++;
358 
359  for (; p != d.end(); p++) {
360  double tmp = apply(*(*p));
361  result = std::max(result, tmp);
362  }
363  result_ = result;
364  };
365 
366  void bvisit(const Min &x)
367  {
368  auto d = x.get_args();
369  auto p = d.begin();
370  double result = apply(*(*p));
371  p++;
372 
373  for (; p != d.end(); p++) {
374  double tmp = apply(*(*p));
375  result = std::min(result, tmp);
376  }
377  result_ = result;
378  };
379 
380  void bvisit(const BooleanAtom &ba)
381  {
382  result_ = ba.get_val();
383  }
384 
385  void bvisit(const Piecewise &pw)
386  {
387  SYMENGINE_ASSERT_MSG(
388  eq(*pw.get_vec().back().second, *boolTrue),
389  "EvalDouble requires a (Expr, True) at the end of Piecewise");
390 
391  for (const auto &expr_pred : pw.get_vec()) {
392  if (apply(*expr_pred.second) == 1.0) {
393  result_ = apply(*expr_pred.first);
394  return;
395  }
396  }
397  throw SymEngineException(
398  "Unexpectedly reached end of Piecewise function.");
399  }
400 };
401 
403  : public EvalRealDoubleVisitor<EvalRealDoubleVisitorPattern>
404 {
405 };
406 
408  : public EvalRealDoubleVisitor<EvalRealDoubleVisitorFinal>
409 {
410 };
411 
413  : public EvalDoubleVisitor<std::complex<double>, EvalComplexDoubleVisitor>
414 {
415 public:
416  // Classes not implemented are
417  // Subs, UpperGamma, LowerGamma, Dirichlet_eta, Zeta
418  // LeviCivita, KroneckerDelta, LambertW
419  // Derivative, ATan2, Gamma
420 
421  using EvalDoubleVisitor::bvisit;
422 
423  void bvisit(const Complex &x)
424  {
425  result_
426  = std::complex<double>(mp_get_d(x.real_), mp_get_d(x.imaginary_));
427  };
428 
429  void bvisit(const ComplexDouble &x)
430  {
431  result_ = x.i;
432  };
433 #ifdef HAVE_SYMENGINE_MPC
434  void bvisit(const ComplexMPC &x)
435  {
436  mpfr_class t(x.get_prec());
437  double real, imag;
438  mpc_real(t.get_mpfr_t(), x.as_mpc().get_mpc_t(), MPFR_RNDN);
439  real = mpfr_get_d(t.get_mpfr_t(), MPFR_RNDN);
440  mpc_imag(t.get_mpfr_t(), x.as_mpc().get_mpc_t(), MPFR_RNDN);
441  imag = mpfr_get_d(t.get_mpfr_t(), MPFR_RNDN);
442  result_ = std::complex<double>(real, imag);
443  }
444 #endif
445 };
446 
447 /*
448  * These two seem to be equivalent and about the same fast.
449  */
450 // typedef double (*fn)(const Basic &);
451 typedef std::function<double(const Basic &)> fn;
452 
453 std::vector<fn> init_eval_double()
454 {
455  std::vector<fn> table;
456  table.assign(TypeID_Count, [](const Basic &x) -> double {
457  throw NotImplementedError("Not Implemented");
458  });
459  table[SYMENGINE_INTEGER] = [](const Basic &x) {
460  double tmp
461  = mp_get_d((down_cast<const Integer &>(x)).as_integer_class());
462  return tmp;
463  };
464  table[SYMENGINE_RATIONAL] = [](const Basic &x) {
465  double tmp
466  = mp_get_d((down_cast<const Rational &>(x)).as_rational_class());
467  return tmp;
468  };
469  table[SYMENGINE_REAL_DOUBLE] = [](const Basic &x) {
470  double tmp = (down_cast<const RealDouble &>(x)).i;
471  return tmp;
472  };
473 #ifdef HAVE_SYMENGINE_MPFR
474  table[SYMENGINE_REAL_MPFR] = [](const Basic &x) {
475  double tmp = mpfr_get_d(down_cast<const RealMPFR &>(x).i.get_mpfr_t(),
476  MPFR_RNDN);
477  return tmp;
478  };
479 #endif
480  table[SYMENGINE_ADD] = [](const Basic &x) {
481  double tmp = 0;
482  for (const auto &p : x.get_args())
483  tmp += eval_double_single_dispatch(*p);
484  return tmp;
485  };
486  table[SYMENGINE_MUL] = [](const Basic &x) {
487  double tmp = 1;
488  for (const auto &p : x.get_args())
489  tmp *= eval_double_single_dispatch(*p);
490  return tmp;
491  };
492  table[SYMENGINE_POW] = [](const Basic &x) {
493  double a = eval_double_single_dispatch(
494  *(down_cast<const Pow &>(x)).get_base());
495  double b = eval_double_single_dispatch(
496  *(down_cast<const Pow &>(x)).get_exp());
497  return ::pow(a, b);
498  };
499  table[SYMENGINE_SIN] = [](const Basic &x) {
500  double tmp = eval_double_single_dispatch(
501  *(down_cast<const Sin &>(x)).get_arg());
502  return ::sin(tmp);
503  };
504  table[SYMENGINE_COS] = [](const Basic &x) {
505  double tmp = eval_double_single_dispatch(
506  *(down_cast<const Cos &>(x)).get_arg());
507  return ::cos(tmp);
508  };
509  table[SYMENGINE_TAN] = [](const Basic &x) {
510  double tmp = eval_double_single_dispatch(
511  *(down_cast<const Tan &>(x)).get_arg());
512  return ::tan(tmp);
513  };
514  table[SYMENGINE_LOG] = [](const Basic &x) {
515  double tmp = eval_double_single_dispatch(
516  *(down_cast<const Log &>(x)).get_arg());
517  return ::log(tmp);
518  };
519  table[SYMENGINE_COT] = [](const Basic &x) {
520  double tmp = eval_double_single_dispatch(
521  *(down_cast<const Cot &>(x)).get_arg());
522  return 1 / ::tan(tmp);
523  };
524  table[SYMENGINE_CSC] = [](const Basic &x) {
525  double tmp = eval_double_single_dispatch(
526  *(down_cast<const Csc &>(x)).get_arg());
527  return 1 / ::sin(tmp);
528  };
529  table[SYMENGINE_SEC] = [](const Basic &x) {
530  double tmp = eval_double_single_dispatch(
531  *(down_cast<const Sec &>(x)).get_arg());
532  return 1 / ::cos(tmp);
533  };
534  table[SYMENGINE_ASIN] = [](const Basic &x) {
535  double tmp = eval_double_single_dispatch(
536  *(down_cast<const ASin &>(x)).get_arg());
537  return ::asin(tmp);
538  };
539  table[SYMENGINE_ACOS] = [](const Basic &x) {
540  double tmp = eval_double_single_dispatch(
541  *(down_cast<const ACos &>(x)).get_arg());
542  return ::acos(tmp);
543  };
544  table[SYMENGINE_ASEC] = [](const Basic &x) {
545  double tmp = eval_double_single_dispatch(
546  *(down_cast<const ASec &>(x)).get_arg());
547  return ::acos(1 / tmp);
548  };
549  table[SYMENGINE_ACSC] = [](const Basic &x) {
550  double tmp = eval_double_single_dispatch(
551  *(down_cast<const ACsc &>(x)).get_arg());
552  return ::asin(1 / tmp);
553  };
554  table[SYMENGINE_ATAN] = [](const Basic &x) {
555  double tmp = eval_double_single_dispatch(
556  *(down_cast<const ATan &>(x)).get_arg());
557  return ::atan(tmp);
558  };
559  table[SYMENGINE_ACOT] = [](const Basic &x) {
560  double tmp = eval_double_single_dispatch(
561  *(down_cast<const ACot &>(x)).get_arg());
562  return ::atan(1 / tmp);
563  };
564  table[SYMENGINE_ATAN2] = [](const Basic &x) {
565  double num = eval_double_single_dispatch(
566  *(down_cast<const ATan2 &>(x)).get_num());
567  double den = eval_double_single_dispatch(
568  *(down_cast<const ATan2 &>(x)).get_den());
569  return ::atan2(num, den);
570  };
571  table[SYMENGINE_SINH] = [](const Basic &x) {
572  double tmp = eval_double_single_dispatch(
573  *(down_cast<const Sinh &>(x)).get_arg());
574  return ::sinh(tmp);
575  };
576  table[SYMENGINE_CSCH] = [](const Basic &x) {
577  double tmp = eval_double_single_dispatch(
578  *(down_cast<const Csch &>(x)).get_arg());
579  return 1 / ::sinh(tmp);
580  };
581  table[SYMENGINE_COSH] = [](const Basic &x) {
582  double tmp = eval_double_single_dispatch(
583  *(down_cast<const Cosh &>(x)).get_arg());
584  return ::cosh(tmp);
585  };
586  table[SYMENGINE_SECH] = [](const Basic &x) {
587  double tmp = eval_double_single_dispatch(
588  *(down_cast<const Sech &>(x)).get_arg());
589  return 1 / ::cosh(tmp);
590  };
591  table[SYMENGINE_TANH] = [](const Basic &x) {
592  double tmp = eval_double_single_dispatch(
593  *(down_cast<const Tanh &>(x)).get_arg());
594  return ::tanh(tmp);
595  };
596  table[SYMENGINE_COTH] = [](const Basic &x) {
597  double tmp = eval_double_single_dispatch(
598  *(down_cast<const Coth &>(x)).get_arg());
599  return 1 / ::tanh(tmp);
600  };
601  table[SYMENGINE_ASINH] = [](const Basic &x) {
602  double tmp = eval_double_single_dispatch(
603  *(down_cast<const ASinh &>(x)).get_arg());
604  return ::asinh(tmp);
605  };
606  table[SYMENGINE_ACSCH] = [](const Basic &x) {
607  double tmp = eval_double_single_dispatch(
608  *(down_cast<const ACsch &>(x)).get_arg());
609  return ::asinh(1 / tmp);
610  };
611  table[SYMENGINE_ACOSH] = [](const Basic &x) {
612  double tmp = eval_double_single_dispatch(
613  *(down_cast<const ACosh &>(x)).get_arg());
614  return ::acosh(tmp);
615  };
616  table[SYMENGINE_ATANH] = [](const Basic &x) {
617  double tmp = eval_double_single_dispatch(
618  *(down_cast<const ATanh &>(x)).get_arg());
619  return ::atanh(tmp);
620  };
621  table[SYMENGINE_ACOTH] = [](const Basic &x) {
622  double tmp = eval_double_single_dispatch(
623  *(down_cast<const ACoth &>(x)).get_arg());
624  return std::atanh(1 / tmp);
625  };
626  table[SYMENGINE_ASECH] = [](const Basic &x) {
627  double tmp = eval_double_single_dispatch(
628  *(down_cast<const ASech &>(x)).get_arg());
629  return ::acosh(1 / tmp);
630  };
631  table[SYMENGINE_GAMMA] = [](const Basic &x) {
632  double tmp = eval_double_single_dispatch(
633  *(down_cast<const Gamma &>(x)).get_args()[0]);
634  return ::tgamma(tmp);
635  };
636  table[SYMENGINE_LOGGAMMA] = [](const Basic &x) {
637  double tmp = eval_double_single_dispatch(
638  *(down_cast<const LogGamma &>(x)).get_args()[0]);
639  return ::lgamma(tmp);
640  };
641  table[SYMENGINE_ERF] = [](const Basic &x) {
642  double tmp = eval_double_single_dispatch(
643  *(down_cast<const Erf &>(x)).get_args()[0]);
644  return ::erf(tmp);
645  };
646  table[SYMENGINE_ERFC] = [](const Basic &x) {
647  double tmp = eval_double_single_dispatch(
648  *(down_cast<const Erfc &>(x)).get_args()[0]);
649  return ::erfc(tmp);
650  };
651  table[SYMENGINE_EQUALITY] = [](const Basic &x) {
652  double lhs = eval_double_single_dispatch(
653  *(down_cast<const Equality &>(x)).get_arg1());
654  double rhs = eval_double_single_dispatch(
655  *(down_cast<const Equality &>(x)).get_arg2());
656  return (lhs == rhs);
657  };
658  table[SYMENGINE_UNEQUALITY] = [](const Basic &x) {
659  double lhs = eval_double_single_dispatch(
660  *(down_cast<const Unequality &>(x)).get_arg1());
661  double rhs = eval_double_single_dispatch(
662  *(down_cast<const Unequality &>(x)).get_arg2());
663  return (lhs != rhs);
664  };
665  table[SYMENGINE_LESSTHAN] = [](const Basic &x) {
666  double lhs = eval_double_single_dispatch(
667  *(down_cast<const LessThan &>(x)).get_arg1());
668  double rhs = eval_double_single_dispatch(
669  *(down_cast<const LessThan &>(x)).get_arg2());
670  return (lhs <= rhs);
671  };
672  table[SYMENGINE_STRICTLESSTHAN] = [](const Basic &x) {
673  double lhs = eval_double_single_dispatch(
674  *(down_cast<const StrictLessThan &>(x)).get_arg1());
675  double rhs = eval_double_single_dispatch(
676  *(down_cast<const StrictLessThan &>(x)).get_arg2());
677  return (lhs < rhs);
678  };
679  table[SYMENGINE_CONSTANT] = [](const Basic &x) {
680  if (eq(x, *pi)) {
681  return std::atan2(0, -1);
682  } else if (eq(x, *E)) {
683  return std::exp(1);
684  } else if (eq(x, *EulerGamma)) {
685  return 0.5772156649015328606065; // use until polygamma or digamma
686  // is implemented
687  } else if (eq(x, *Catalan)) {
688  return 0.9159655941772190150546;
689  } else if (eq(x, *GoldenRatio)) {
690  return 1.6180339887498948482045;
691  } else {
692  throw NotImplementedError(
693  "Constant " + down_cast<const Constant &>(x).get_name()
694  + " is not implemented.");
695  }
696  };
697  table[SYMENGINE_ABS] = [](const Basic &x) {
698  double tmp = eval_double_single_dispatch(
699  *(down_cast<const Abs &>(x)).get_arg());
700  return std::abs(tmp);
701  };
702  table[SYMENGINE_MAX] = [](const Basic &x) {
703  double result;
704  result = eval_double_single_dispatch(
705  *(down_cast<const Max &>(x).get_args()[0]));
706  for (const auto &p : down_cast<const Max &>(x).get_args()) {
707  double tmp = eval_double_single_dispatch(*p);
708  result = std::max(result, tmp);
709  }
710  return result;
711  };
712  table[SYMENGINE_MIN] = [](const Basic &x) {
713  double result;
714  result = eval_double_single_dispatch(
715  *(down_cast<const Min &>(x).get_args()[0]));
716  for (const auto &p : down_cast<const Min &>(x).get_args()) {
717  double tmp = eval_double_single_dispatch(*p);
718  result = std::min(result, tmp);
719  }
720  return result;
721  };
722  return table;
723 }
724 
725 const static std::vector<fn> table_eval_double = init_eval_double();
726 
727 double eval_double(const Basic &b)
728 {
729  EvalRealDoubleVisitorFinal v;
730  return v.apply(b);
731 }
732 
733 std::complex<double> eval_complex_double(const Basic &b)
734 {
735  EvalComplexDoubleVisitor v;
736  return v.apply(b);
737 }
738 
739 double eval_double_single_dispatch(const Basic &b)
740 {
741  return table_eval_double[b.get_type_code()](b);
742 }
743 
744 double eval_double_visitor_pattern(const Basic &b)
745 {
746  EvalRealDoubleVisitorPattern v;
747  return v.apply(b);
748 }
749 
750 #define ACCEPT(CLASS) \
751  void CLASS::accept(EvalRealDoubleVisitorFinal &v) const \
752  { \
753  v.bvisit(*this); \
754  }
755 
756 #define SYMENGINE_ENUM(TypeID, Class) ACCEPT(Class)
757 #include "symengine/type_codes.inc"
758 #undef SYMENGINE_ENUM
759 
760 } // namespace SymEngine
T acos(T... args)
T acosh(T... args)
T asin(T... args)
T asinh(T... args)
T assign(T... args)
T atan2(T... args)
T atan(T... args)
T atanh(T... args)
T back(T... args)
T begin(T... args)
RCP< const Basic > get_den() const
Definition: functions.h:516
RCP< const Basic > get_num() const
Definition: functions.h:511
The base class for representing addition in symbolic expressions.
Definition: add.h:27
virtual vec_basic get_args() const
Returns the arguments of the Add.
Definition: add.cpp:397
The lowest unit of symbolic representation.
Definition: basic.h:95
virtual vec_basic get_args() const =0
Returns the list of arguments.
Complex Double Class to hold std::complex<double> values.
Complex Class.
Definition: complex.h:33
rational_class real_
Definition: complex.h:38
std::string get_name() const
Definition: constants.h:41
Integer Class.
Definition: integer.h:19
const integer_class & as_integer_class() const
Convert to integer_class.
Definition: integer.h:48
virtual vec_basic get_args() const
Returns the list of arguments.
Definition: mul.cpp:502
virtual vec_basic get_args() const
Returns the list of arguments.
Definition: functions.h:159
virtual vec_basic get_args() const
Returns the list of arguments.
Definition: functions.h:40
RCP< const Basic > get_arg() const
Definition: functions.h:36
RCP< const Basic > get_exp() const
Definition: pow.h:42
RCP< const Basic > get_base() const
Definition: pow.h:37
Rational Class.
Definition: rational.h:16
const rational_class & as_rational_class() const
Convert to rational_class.
Definition: rational.h:50
RealDouble Class to hold double values.
Definition: real_double.h:20
RCP< const Basic > get_arg1() const
Definition: functions.h:91
RCP< const Basic > get_arg2() const
Definition: functions.h:96
T cos(T... args)
T cosh(T... args)
T erf(T... args)
T erfc(T... args)
T exp(T... args)
T lgamma(T... args)
T log(T... args)
T max(T... args)
T min(T... args)
Main namespace for SymEngine package.
Definition: add.cpp:19
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
Definition: basic-inl.h:21
RCP< const Basic > tan(const RCP< const Basic > &arg)
Canonicalize Tan:
Definition: functions.cpp:964
RCP< const Basic > cosh(const RCP< const Basic > &arg)
Canonicalize Cosh:
Definition: functions.cpp:2169
RCP< const Basic > tanh(const RCP< const Basic > &arg)
Canonicalize Tanh:
Definition: functions.cpp:2247
@ TypeID_Count
Definition: basic.h:52
RCP< const Basic > cos(const RCP< const Basic > &arg)
Canonicalize Cos:
Definition: functions.cpp:899
RCP< const Basic > sinh(const RCP< const Basic > &arg)
Canonicalize Sinh:
Definition: functions.cpp:2084
RCP< const Basic > sin(const RCP< const Basic > &arg)
Canonicalize Sin:
Definition: functions.cpp:831
T pow(T... args)
T sin(T... args)
T sinh(T... args)
T tan(T... args)
T tanh(T... args)
T tgamma(T... args)