Loading...
Searching...
No Matches
eval_double.cpp
1#include <symengine/visitor.h>
3#include <symengine/symengine_exception.h>
4
5namespace SymEngine
6{
7
8template <typename T, typename C>
10{
11protected:
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
21public:
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
280template <typename C>
282{
283public:
284 // Classes not implemented are
285 // Subs, UpperGamma, LowerGamma, Dirichlet_eta, Zeta
286 // LeviCivita, KroneckerDelta, LambertW
287 // Derivative, Complex, ComplexDouble, ComplexMPC
288
289 using EvalDoubleVisitor<double, C>::bvisit;
290 using EvalDoubleVisitor<double, C>::apply;
291 using EvalDoubleVisitor<double, C>::result_;
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));
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));
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{
415public:
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 &);
451typedef std::function<double(const Basic &)> fn;
452
453static inline std::vector<fn> init_eval_double()
454{
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 {
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);
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);
719 }
720 return result;
721 };
722 return table;
723}
724
725double eval_double(const Basic &b)
726{
727 EvalRealDoubleVisitorFinal v;
728 return v.apply(b);
729}
730
731std::complex<double> eval_complex_double(const Basic &b)
732{
733 EvalComplexDoubleVisitor v;
734 return v.apply(b);
735}
736
737double eval_double_single_dispatch(const Basic &b)
738{
739 static const std::vector<fn> table_eval_double = init_eval_double();
740 return table_eval_double[b.get_type_code()](b);
741}
742
743double eval_double_visitor_pattern(const Basic &b)
744{
745 EvalRealDoubleVisitorPattern v;
746 return v.apply(b);
747}
748
749#define ACCEPT(CLASS) \
750 void CLASS::accept(EvalRealDoubleVisitorFinal &v) const \
751 { \
752 v.bvisit(*this); \
753 }
754
755#define SYMENGINE_ENUM(TypeID, Class) ACCEPT(Class)
756#include "symengine/type_codes.inc"
757#undef SYMENGINE_ENUM
758
759} // 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 begin(T... args)
RCP< const Basic > get_num() const
Definition functions.h:511
RCP< const Basic > get_den() const
Definition functions.h:516
The base class for representing addition in symbolic expressions.
Definition add.h:27
vec_basic get_args() const override
Returns the arguments of the Add.
Definition add.cpp:397
The lowest unit of symbolic representation.
Definition basic.h:97
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:45
vec_basic get_args() const override
Returns the list of arguments.
Definition mul.cpp:507
vec_basic get_args() const override
Returns the list of arguments.
Definition functions.h:159
RCP< const Basic > get_arg() const
Definition functions.h:36
vec_basic get_args() const override
Returns the list of arguments.
Definition functions.h:40
RCP< const Basic > get_base() const
Definition pow.h:37
RCP< const Basic > get_exp() const
Definition pow.h:42
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_arg2() const
Definition functions.h:96
RCP< const Basic > get_arg1() const
Definition functions.h:91
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
void hash_combine(hash_t &seed, const T &v)
Definition basic-inl.h:95
RCP< const Basic > tan(const RCP< const Basic > &arg)
Canonicalize Tan:
RCP< const Basic > cosh(const RCP< const Basic > &arg)
Canonicalize Cosh:
RCP< const Basic > tanh(const RCP< const Basic > &arg)
Canonicalize Tanh:
@ TypeID_Count
Definition basic.h:52
RCP< const Basic > cos(const RCP< const Basic > &arg)
Canonicalize Cos:
RCP< const Basic > sinh(const RCP< const Basic > &arg)
Canonicalize Sinh:
RCP< const Basic > sin(const RCP< const Basic > &arg)
Canonicalize Sin:
T pow(T... args)
T sin(T... args)
T sinh(T... args)
T tan(T... args)
T tanh(T... args)
T tgamma(T... args)