3 #include <symengine/symengine_exception.h>
8 template <
typename T,
typename C>
22 T apply(
const Basic &b)
24 b.accept(*down_cast<C *>(
this));
45 #ifdef HAVE_SYMENGINE_MPFR
48 T tmp = mpfr_get_d(x.i.get_mpfr_t(), MPFR_RNDN);
52 void bvisit(
const Add &x)
60 void bvisit(
const Mul &x)
68 void bvisit(
const Pow &x)
79 void bvisit(
const Sin &x)
85 void bvisit(
const Cos &x)
91 void bvisit(
const Tan &x)
97 void bvisit(
const Symbol &)
99 throw SymEngineException(
"Symbol cannot be evaluated.");
102 void bvisit(
const Log &x)
108 void bvisit(
const Cot &x)
114 void bvisit(
const Csc &x)
120 void bvisit(
const Sec &x)
126 void bvisit(
const ASin &x)
132 void bvisit(
const ACos &x)
138 void bvisit(
const ASec &x)
144 void bvisit(
const ACsc &x)
150 void bvisit(
const ATan &x)
156 void bvisit(
const ACot &x)
162 void bvisit(
const Sinh &x)
168 void bvisit(
const Csch &x)
174 void bvisit(
const Cosh &x)
180 void bvisit(
const Sech &x)
186 void bvisit(
const Tanh &x)
192 void bvisit(
const Coth &x)
198 void bvisit(
const ASinh &x)
204 void bvisit(
const ACsch &x)
210 void bvisit(
const ACosh &x)
216 void bvisit(
const ATanh &x)
222 void bvisit(
const ACoth &x)
228 void bvisit(
const ASech &x)
238 }
else if (
eq(x, *E)) {
240 }
else if (
eq(x, *EulerGamma)) {
241 result_ = 0.5772156649015328606065;
243 }
else if (
eq(x, *Catalan)) {
244 result_ = 0.9159655941772190150546;
245 }
else if (
eq(x, *GoldenRatio)) {
246 result_ = 1.6180339887498948482045;
248 throw NotImplementedError(
"Constant " + x.
get_name()
249 +
" is not implemented.");
253 void bvisit(
const Abs &x)
256 result_ = std::abs(tmp);
259 void bvisit(
const Basic &)
261 throw NotImplementedError(
"Not Implemented");
266 apply(*(x.eval(53)));
271 apply(*(x.eval(53)));
280 template <
typename C>
293 void bvisit(
const ATan2 &x)
295 double num = apply(*(x.
get_num()));
296 double den = apply(*(x.
get_den()));
300 void bvisit(
const Gamma &x)
302 double tmp = apply(*(x.
get_args()[0]));
308 double tmp = apply(*(x.
get_args()[0]));
312 void bvisit(
const Erf &x)
314 double tmp = apply(*(x.
get_args()[0]));
318 void bvisit(
const Erfc &x)
320 double tmp = apply(*(x.
get_args()[0]));
326 double lhs_ = apply(*(x.
get_arg1()));
327 double rhs_ = apply(*(x.
get_arg2()));
328 result_ = (lhs_ == rhs_);
333 double lhs_ = apply(*(x.
get_arg1()));
334 double rhs_ = apply(*(x.
get_arg2()));
335 result_ = (lhs_ != rhs_);
340 double lhs_ = apply(*(x.
get_arg1()));
341 double rhs_ = apply(*(x.
get_arg2()));
342 result_ = (lhs_ <= rhs_);
347 double lhs_ = apply(*(x.
get_arg1()));
348 double rhs_ = apply(*(x.
get_arg2()));
349 result_ = (lhs_ < rhs_);
352 void bvisit(
const Max &x)
356 double result = apply(*(*p));
359 for (; p != d.end(); p++) {
360 double tmp = apply(*(*p));
366 void bvisit(
const Min &x)
370 double result = apply(*(*p));
373 for (; p != d.end(); p++) {
374 double tmp = apply(*(*p));
382 result_ = ba.get_val();
387 SYMENGINE_ASSERT_MSG(
388 eq(*pw.get_vec().
back().second, *boolTrue),
389 "EvalDouble requires a (Expr, True) at the end of Piecewise");
391 for (
const auto &expr_pred : pw.get_vec()) {
392 if (apply(*expr_pred.second) == 1.0) {
393 result_ = apply(*expr_pred.first);
397 throw SymEngineException(
398 "Unexpectedly reached end of Piecewise function.");
421 using EvalDoubleVisitor::bvisit;
433 #ifdef HAVE_SYMENGINE_MPC
436 mpfr_class t(x.get_prec());
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);
457 throw NotImplementedError(
"Not Implemented");
459 table[SYMENGINE_INTEGER] = [](
const Basic &x) {
461 = mp_get_d((down_cast<const Integer &>(x)).as_integer_class());
464 table[SYMENGINE_RATIONAL] = [](
const Basic &x) {
466 = mp_get_d((down_cast<const Rational &>(x)).as_rational_class());
469 table[SYMENGINE_REAL_DOUBLE] = [](
const Basic &x) {
470 double tmp = (down_cast<const RealDouble &>(x)).i;
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(),
480 table[SYMENGINE_ADD] = [](
const Basic &x) {
483 tmp += eval_double_single_dispatch(*p);
486 table[SYMENGINE_MUL] = [](
const Basic &x) {
489 tmp *= eval_double_single_dispatch(*p);
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());
499 table[SYMENGINE_SIN] = [](
const Basic &x) {
500 double tmp = eval_double_single_dispatch(
501 *(down_cast<const Sin &>(x)).get_arg());
504 table[SYMENGINE_COS] = [](
const Basic &x) {
505 double tmp = eval_double_single_dispatch(
506 *(down_cast<const Cos &>(x)).get_arg());
509 table[SYMENGINE_TAN] = [](
const Basic &x) {
510 double tmp = eval_double_single_dispatch(
511 *(down_cast<const Tan &>(x)).get_arg());
514 table[SYMENGINE_LOG] = [](
const Basic &x) {
515 double tmp = eval_double_single_dispatch(
516 *(down_cast<const Log &>(x)).get_arg());
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);
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);
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);
534 table[SYMENGINE_ASIN] = [](
const Basic &x) {
535 double tmp = eval_double_single_dispatch(
536 *(down_cast<const ASin &>(x)).get_arg());
539 table[SYMENGINE_ACOS] = [](
const Basic &x) {
540 double tmp = eval_double_single_dispatch(
541 *(down_cast<const ACos &>(x)).get_arg());
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);
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);
554 table[SYMENGINE_ATAN] = [](
const Basic &x) {
555 double tmp = eval_double_single_dispatch(
556 *(down_cast<const ATan &>(x)).get_arg());
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);
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);
571 table[SYMENGINE_SINH] = [](
const Basic &x) {
572 double tmp = eval_double_single_dispatch(
573 *(down_cast<const Sinh &>(x)).get_arg());
576 table[SYMENGINE_CSCH] = [](
const Basic &x) {
577 double tmp = eval_double_single_dispatch(
578 *(down_cast<const Csch &>(x)).get_arg());
581 table[SYMENGINE_COSH] = [](
const Basic &x) {
582 double tmp = eval_double_single_dispatch(
583 *(down_cast<const Cosh &>(x)).get_arg());
586 table[SYMENGINE_SECH] = [](
const Basic &x) {
587 double tmp = eval_double_single_dispatch(
588 *(down_cast<const Sech &>(x)).get_arg());
591 table[SYMENGINE_TANH] = [](
const Basic &x) {
592 double tmp = eval_double_single_dispatch(
593 *(down_cast<const Tanh &>(x)).get_arg());
596 table[SYMENGINE_COTH] = [](
const Basic &x) {
597 double tmp = eval_double_single_dispatch(
598 *(down_cast<const Coth &>(x)).get_arg());
601 table[SYMENGINE_ASINH] = [](
const Basic &x) {
602 double tmp = eval_double_single_dispatch(
603 *(down_cast<const ASinh &>(x)).get_arg());
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);
611 table[SYMENGINE_ACOSH] = [](
const Basic &x) {
612 double tmp = eval_double_single_dispatch(
613 *(down_cast<const ACosh &>(x)).get_arg());
616 table[SYMENGINE_ATANH] = [](
const Basic &x) {
617 double tmp = eval_double_single_dispatch(
618 *(down_cast<const ATanh &>(x)).get_arg());
621 table[SYMENGINE_ACOTH] = [](
const Basic &x) {
622 double tmp = eval_double_single_dispatch(
623 *(down_cast<const ACoth &>(x)).get_arg());
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);
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);
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);
641 table[SYMENGINE_ERF] = [](
const Basic &x) {
642 double tmp = eval_double_single_dispatch(
643 *(down_cast<const Erf &>(x)).get_args()[0]);
646 table[SYMENGINE_ERFC] = [](
const Basic &x) {
647 double tmp = eval_double_single_dispatch(
648 *(down_cast<const Erfc &>(x)).get_args()[0]);
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());
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());
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());
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());
679 table[SYMENGINE_CONSTANT] = [](
const Basic &x) {
682 }
else if (
eq(x, *E)) {
684 }
else if (
eq(x, *EulerGamma)) {
685 return 0.5772156649015328606065;
687 }
else if (
eq(x, *Catalan)) {
688 return 0.9159655941772190150546;
689 }
else if (
eq(x, *GoldenRatio)) {
690 return 1.6180339887498948482045;
692 throw NotImplementedError(
693 "Constant " + down_cast<const Constant &>(x).get_name()
694 +
" is not implemented.");
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);
702 table[SYMENGINE_MAX] = [](
const Basic &x) {
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);
712 table[SYMENGINE_MIN] = [](
const Basic &x) {
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);
725 double eval_double(
const Basic &b)
727 EvalRealDoubleVisitorFinal v;
733 EvalComplexDoubleVisitor v;
737 double eval_double_single_dispatch(
const Basic &b)
740 return table_eval_double[b.get_type_code()](b);
743 double eval_double_visitor_pattern(
const Basic &b)
745 EvalRealDoubleVisitorPattern v;
749 #define ACCEPT(CLASS) \
750 void CLASS::accept(EvalRealDoubleVisitorFinal &v) const \
755 #define SYMENGINE_ENUM(TypeID, Class) ACCEPT(Class)
756 #include "symengine/type_codes.inc"
757 #undef SYMENGINE_ENUM
RCP< const Basic > get_den() const
RCP< const Basic > get_num() const
The base class for representing addition in symbolic expressions.
vec_basic get_args() const override
Returns the arguments of the Add.
The lowest unit of symbolic representation.
virtual vec_basic get_args() const =0
Returns the list of arguments.
Complex Double Class to hold std::complex<double> values.
std::string get_name() const
const integer_class & as_integer_class() const
Convert to integer_class.
vec_basic get_args() const override
Returns the list of arguments.
vec_basic get_args() const override
Returns the list of arguments.
vec_basic get_args() const override
Returns the list of arguments.
RCP< const Basic > get_arg() const
RCP< const Basic > get_exp() const
RCP< const Basic > get_base() const
const rational_class & as_rational_class() const
Convert to rational_class.
RealDouble Class to hold double values.
RCP< const Basic > get_arg1() const
RCP< const Basic > get_arg2() const
Main namespace for SymEngine package.
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
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:
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: