1#include <symengine/test_visitors.h>
6void ZeroVisitor::error()
8 throw SymEngineException(
9 "Only numeric types allowed for is_zero/is_nonzero");
12void ZeroVisitor::bvisit(
const Basic &x)
14 is_zero_ = tribool::indeterminate;
17void ZeroVisitor::bvisit(
const Set &x)
22void ZeroVisitor::bvisit(
const Relational &x)
27void ZeroVisitor::bvisit(
const Boolean &x)
32void ZeroVisitor::bvisit(
const Constant &x)
34 is_zero_ = tribool::trifalse;
37void ZeroVisitor::bvisit(
const Abs &x)
39 x.get_arg()->accept(*
this);
42void ZeroVisitor::bvisit(
const Conjugate &x)
44 x.get_arg()->accept(*
this);
47void ZeroVisitor::bvisit(
const Sign &x)
49 x.get_arg()->accept(*
this);
52void ZeroVisitor::bvisit(
const PrimePi &x)
55 is_zero_ = is_negative(*
sub(x.get_arg(),
integer(2)));
58void ZeroVisitor::bvisit(
const Number &x)
60 if (
bool(x.is_zero())) {
61 is_zero_ = tribool::tritrue;
63 is_zero_ = tribool::trifalse;
67void ZeroVisitor::bvisit(
const Symbol &x)
70 is_zero_ = assumptions_->is_zero(x.rcp_from_this());
72 is_zero_ = tribool::indeterminate;
76tribool ZeroVisitor::apply(
const Basic &b)
85 return visitor.apply(b);
91 return not_tribool(visitor.apply(b));
94void PositiveVisitor::error()
96 throw SymEngineException(
"Only numeric types allowed for is_positive");
99void PositiveVisitor::bvisit(
const Constant &x)
101 is_positive_ = tribool::tritrue;
104void PositiveVisitor::bvisit(
const Basic &x)
106 is_positive_ = tribool::indeterminate;
109void PositiveVisitor::bvisit(
const Set &x)
114void PositiveVisitor::bvisit(
const Relational &x)
119void PositiveVisitor::bvisit(
const Boolean &x)
124void PositiveVisitor::bvisit(
const Symbol &x)
127 is_positive_ = assumptions_->is_positive(x.rcp_from_this());
129 is_positive_ = tribool::indeterminate;
133void PositiveVisitor::bvisit(
const Number &x)
136 is_positive_ = tribool::trifalse;
137 }
else if (
bool(x.is_positive())) {
138 is_positive_ = tribool::tritrue;
140 is_positive_ = tribool::trifalse;
144void PositiveVisitor::bvisit(
const Add &x)
148 auto coef = x.get_coef();
149 auto dict = x.get_dict();
151 bool can_be_true =
true;
152 bool can_be_false =
true;
153 if (coef->is_positive()) {
154 can_be_false =
false;
155 }
else if (coef->is_negative()) {
158 NegativeVisitor neg_visitor(assumptions_);
159 for (
const auto &p : dict) {
160 if (not can_be_true and not can_be_false) {
161 is_positive_ = tribool::indeterminate;
164 p.first->accept(*
this);
165 if ((p.second->is_positive() and is_true(is_positive_))
166 or (p.second->is_negative()
167 and is_true(neg_visitor.apply(*p.first)))) {
169 can_be_false =
false;
170 }
else if ((p.second->is_negative() and is_true(is_positive_))
171 or (p.second->is_positive()
172 and is_true(neg_visitor.apply(*p.first)))) {
177 can_be_false =
false;
181 is_positive_ = tribool::tritrue;
182 }
else if (can_be_false) {
183 is_positive_ = tribool::trifalse;
185 is_positive_ = tribool::indeterminate;
189tribool PositiveVisitor::apply(
const Basic &b)
195tribool is_positive(
const Basic &b,
const Assumptions *assumptions)
197 PositiveVisitor visitor(assumptions);
198 return visitor.apply(b);
201void NonPositiveVisitor::error()
203 throw SymEngineException(
"Only numeric types allowed for is_negative");
206void NonPositiveVisitor::bvisit(
const Constant &x)
208 is_nonpositive_ = tribool::trifalse;
211void NonPositiveVisitor::bvisit(
const Basic &x)
213 is_nonpositive_ = tribool::indeterminate;
216void NonPositiveVisitor::bvisit(
const Set &x)
221void NonPositiveVisitor::bvisit(
const Relational &x)
226void NonPositiveVisitor::bvisit(
const Boolean &x)
231void NonPositiveVisitor::bvisit(
const Symbol &x)
234 is_nonpositive_ = assumptions_->is_nonpositive(x.rcp_from_this());
236 is_nonpositive_ = tribool::indeterminate;
240void NonPositiveVisitor::bvisit(
const Number &x)
243 is_nonpositive_ = tribool::trifalse;
244 }
else if (
bool(x.is_positive())) {
245 is_nonpositive_ = tribool::trifalse;
247 is_nonpositive_ = tribool::tritrue;
251tribool NonPositiveVisitor::apply(
const Basic &b)
254 return is_nonpositive_;
257tribool is_nonpositive(
const Basic &b,
const Assumptions *assumptions)
259 NonPositiveVisitor visitor(assumptions);
260 return visitor.apply(b);
263void NegativeVisitor::error()
265 throw SymEngineException(
"Only numeric types allowed for is_negative");
268void NegativeVisitor::bvisit(
const Basic &x)
270 is_negative_ = tribool::indeterminate;
273void NegativeVisitor::bvisit(
const Set &x)
278void NegativeVisitor::bvisit(
const Relational &x)
283void NegativeVisitor::bvisit(
const Boolean &x)
288void NegativeVisitor::bvisit(
const Constant &x)
290 is_negative_ = tribool::trifalse;
293void NegativeVisitor::bvisit(
const Symbol &x)
296 is_negative_ = assumptions_->is_negative(x.rcp_from_this());
298 is_negative_ = tribool::indeterminate;
302void NegativeVisitor::bvisit(
const Number &x)
305 is_negative_ = tribool::trifalse;
306 }
else if (
bool(x.is_negative())) {
307 is_negative_ = tribool::tritrue;
309 is_negative_ = tribool::trifalse;
313tribool NegativeVisitor::apply(
const Basic &b)
319tribool is_negative(
const Basic &b,
const Assumptions *assumptions)
321 NegativeVisitor visitor(assumptions);
322 return visitor.apply(b);
325void NonNegativeVisitor::error()
327 throw SymEngineException(
"Only numeric types allowed for is_nonnegative");
330void NonNegativeVisitor::bvisit(
const Basic &x)
332 is_nonnegative_ = tribool::indeterminate;
335void NonNegativeVisitor::bvisit(
const Set &x)
340void NonNegativeVisitor::bvisit(
const Relational &x)
345void NonNegativeVisitor::bvisit(
const Boolean &x)
350void NonNegativeVisitor::bvisit(
const Constant &x)
352 is_nonnegative_ = tribool::tritrue;
355void NonNegativeVisitor::bvisit(
const Symbol &x)
358 is_nonnegative_ = assumptions_->is_nonnegative(x.rcp_from_this());
360 is_nonnegative_ = tribool::indeterminate;
364void NonNegativeVisitor::bvisit(
const Number &x)
367 is_nonnegative_ = tribool::trifalse;
368 }
else if (
bool(x.is_negative())) {
369 is_nonnegative_ = tribool::trifalse;
371 is_nonnegative_ = tribool::tritrue;
375tribool NonNegativeVisitor::apply(
const Basic &b)
378 return is_nonnegative_;
381tribool is_nonnegative(
const Basic &b,
const Assumptions *assumptions)
383 NonNegativeVisitor visitor(assumptions);
384 return visitor.apply(b);
387void IntegerVisitor::bvisit(
const Symbol &x)
390 is_integer_ = assumptions_->is_integer(x.rcp_from_this());
392 is_integer_ = tribool::indeterminate;
396void IntegerVisitor::bvisit(
const Constant &x)
398 if (
eq(x, *pi) or
eq(x, *E) or
eq(x, *EulerGamma) or
eq(x, *Catalan)
399 or
eq(x, *GoldenRatio)) {
400 is_integer_ = tribool::trifalse;
402 is_integer_ = tribool::indeterminate;
406void IntegerVisitor::bvisit(
const Add &x)
408 for (
const auto &arg : x.get_args()) {
410 if (not is_true(is_integer_)) {
411 is_integer_ = tribool::indeterminate;
417void IntegerVisitor::bvisit(
const Mul &x)
419 for (
const auto &arg : x.get_args()) {
421 if (not is_true(is_integer_)) {
422 is_integer_ = tribool::indeterminate;
428tribool IntegerVisitor::apply(
const Basic &b)
434tribool is_integer(
const Basic &b,
const Assumptions *assumptions)
436 IntegerVisitor visitor(assumptions);
437 return visitor.apply(b);
440void RealVisitor::bvisit(
const Symbol &x)
443 is_real_ = assumptions_->is_real(x.rcp_from_this());
445 is_real_ = tribool::indeterminate;
449void RealVisitor::bvisit(
const Number &x)
451 if (
is_a_Complex(x) or is_a<Infty>(x) or is_a<NaN>(x)) {
452 is_real_ = tribool::trifalse;
454 is_real_ = tribool::tritrue;
458void RealVisitor::bvisit(
const Constant &x)
460 if (
eq(x, *pi) or
eq(x, *E) or
eq(x, *EulerGamma) or
eq(x, *Catalan)
461 or
eq(x, *GoldenRatio)) {
462 is_real_ = tribool::tritrue;
464 is_real_ = tribool::indeterminate;
468void RealVisitor::bvisit(
const Add &x)
470 tribool b = tribool::tritrue;
471 for (
const auto &arg : x.get_args()) {
473 b = andwk_tribool(b, is_real_);
474 if (is_indeterminate(b)) {
481void RealVisitor::check_power(
const RCP<const Basic> &base,
482 const RCP<const Basic> &
exp)
484 if (is_true(is_zero(*
exp, assumptions_))) {
486 is_real_ = tribool::tritrue;
490 if (is_true(is_real_)) {
491 if (is_true(is_integer(*
exp, assumptions_))) {
493 is_real_ = tribool::tritrue;
494 }
else if (is_true(is_nonnegative(*base, assumptions_))) {
497 if (is_false(is_real_)) {
498 is_real_ = tribool::indeterminate;
501 is_real_ = tribool::indeterminate;
503 }
else if (is_false(is_real_) && is_true(is_complex(*base, assumptions_))
506 is_real_ = tribool::trifalse;
508 is_real_ = tribool::indeterminate;
512void RealVisitor::bvisit(
const Mul &x)
514 unsigned non_real = 0;
515 tribool b = tribool_from_bool(!x.get_coef()->is_complex());
519 for (
const auto &p : x.get_dict()) {
520 this->check_power(p.first, p.second);
521 if (is_false(is_real_)) {
524 is_real_ = tribool::indeterminate;
528 b = andwk_tribool(b, is_real_);
529 if (is_indeterminate(b)) {
530 is_real_ = tribool::indeterminate;
535 is_real_ = tribool::trifalse;
541void RealVisitor::bvisit(
const Pow &x)
543 this->check_power(x.get_base(), x.get_exp());
546tribool RealVisitor::apply(
const Basic &b)
552tribool is_real(
const Basic &b,
const Assumptions *assumptions)
554 RealVisitor visitor(assumptions);
555 return visitor.apply(b);
558void ComplexVisitor::bvisit(
const Symbol &x)
561 is_complex_ = assumptions_->is_complex(x.rcp_from_this());
563 is_complex_ = tribool::indeterminate;
567void ComplexVisitor::bvisit(
const Number &x)
569 if (is_a<Infty>(x) or is_a<NaN>(x)) {
570 is_complex_ = tribool::trifalse;
572 is_complex_ = tribool::tritrue;
576void ComplexVisitor::bvisit(
const Add &x)
578 tribool b = tribool::tritrue;
579 for (
const auto &arg : x.get_args()) {
581 b = andwk_tribool(b, is_complex_);
582 if (is_indeterminate(b) or is_false(b))
587void ComplexVisitor::bvisit(
const Mul &x)
589 tribool b = tribool::tritrue;
590 for (
const auto &p : x.get_dict()) {
591 this->check_power(*p.first, *p.second);
592 b = andwk_tribool(b, is_complex_);
593 if (is_indeterminate(b) or is_false(b))
598void ComplexVisitor::check_power(
const Basic &base,
const Basic &
exp)
601 if (is_true(is_complex_)) {
606void ComplexVisitor::bvisit(
const Pow &x)
608 check_power(*x.get_base(), *x.get_exp());
611void ComplexVisitor::bvisit(
const Log &x)
613 complex_arg_not_zero(x, *x.get_arg());
616void ComplexVisitor::bvisit(
const Tan &x)
618 complex_arg_not_zero(x, *
cos(x.get_arg()));
621void ComplexVisitor::complex_arg_not_zero(
const OneArgFunction &x,
622 const Basic ¬_zero)
625 x.get_arg()->accept(*
this);
626 if (is_true(is_complex_)) {
627 tribool zero = is_zero(not_zero);
628 if (not is_false(zero)) {
629 is_complex_ = not_tribool(zero);
634void ComplexVisitor::complex_arg_not_pm(
const OneArgFunction &x,
bool one)
638 x.get_arg()->accept(*
this);
639 if (not is_true(is_complex_))
641 RCP<const Number> i1;
646 tribool zi1 = is_zero(*
sub(x.get_arg(), i1));
647 if (not is_false(zi1)) {
648 is_complex_ = not_tribool(zi1);
651 RCP<const Number> mi1;
656 tribool zmi1 = is_zero(*
sub(x.get_arg(), mi1));
657 is_complex_ = not_tribool(zmi1);
660void ComplexVisitor::bvisit(
const ATan &x)
662 complex_arg_not_pm(x,
false);
665void ComplexVisitor::bvisit(
const ATanh &x)
667 complex_arg_not_pm(x,
true);
670void ComplexVisitor::bvisit(
const ACot &x)
672 complex_arg_not_pm(x,
false);
675void ComplexVisitor::bvisit(
const ACoth &x)
677 complex_arg_not_pm(x,
true);
680void ComplexVisitor::bvisit(
const Cot &x)
682 complex_arg_not_zero(x, *
sin(x.get_arg()));
685void ComplexVisitor::bvisit(
const Sec &x)
687 complex_arg_not_zero(x, *
cos(x.get_arg()));
690void ComplexVisitor::bvisit(
const ASec &x)
692 complex_arg_not_zero(x, *x.get_arg());
695void ComplexVisitor::bvisit(
const ASech &x)
697 complex_arg_not_zero(x, *x.get_arg());
700void ComplexVisitor::bvisit(
const Csc &x)
702 complex_arg_not_zero(x, *
sin(x.get_arg()));
705void ComplexVisitor::bvisit(
const ACsc &x)
707 complex_arg_not_zero(x, *x.get_arg());
710void ComplexVisitor::bvisit(
const ACsch &x)
712 complex_arg_not_zero(x, *x.get_arg());
715tribool ComplexVisitor::apply(
const Basic &b)
721tribool is_complex(
const Basic &b,
const Assumptions *assumptions)
723 ComplexVisitor visitor(assumptions);
724 return visitor.apply(b);
727void PolynomialVisitor::bvisit(
const Basic &x)
729 auto old_allowed = variables_allowed_;
730 variables_allowed_ =
false;
731 for (
const auto &p : x.get_args()) {
733 if (!is_polynomial_) {
734 variables_allowed_ = old_allowed;
738 variables_allowed_ = old_allowed;
741void PolynomialVisitor::bvisit(
const Add &x)
743 for (
const auto &arg : x.get_args()) {
750void PolynomialVisitor::bvisit(
const Mul &x)
752 for (
const auto &p : x.get_dict()) {
753 this->check_power(*p.first, *p.second);
759void PolynomialVisitor::check_power(
const Basic &base,
const Basic &
exp)
761 if (variables_allowed_) {
762 variables_allowed_ =
false;
764 if (!is_polynomial_) {
765 variables_allowed_ =
true;
769 variables_allowed_ =
true;
770 if (!is_polynomial_) {
771 is_polynomial_ =
true;
773 is_polynomial_ = is_polynomial_ and is_a<Integer>(
exp)
774 and down_cast<const Integer &>(
exp).is_positive();
784void PolynomialVisitor::bvisit(
const Pow &x)
786 check_power(*x.get_base(), *x.get_exp());
789void PolynomialVisitor::bvisit(
const Symbol &x)
791 if (variables_allowed_)
794 if (variables_.
empty()) {
795 is_polynomial_ =
false;
797 for (
const auto &elem : variables_) {
798 if (x.__eq__(*elem)) {
799 is_polynomial_ =
false;
806bool PolynomialVisitor::apply(
const Basic &b)
809 return is_polynomial_;
815 return visitor.apply(b);
818void RationalVisitor::bvisit(
const Number &x)
820 is_rational_ = tribool::trifalse;
821 if (
is_a_Complex(x) or is_a<Infty>(x) or is_a<NaN>(x)) {
826void RationalVisitor::bvisit(
const Constant &x)
828 if (
eq(x, *pi) or
eq(x, *E) or
eq(x, *GoldenRatio)) {
831 is_rational_ = tribool::trifalse;
833 is_rational_ = tribool::indeterminate;
837void RationalVisitor::bvisit(
const Add &x)
839 tribool b = tribool::tritrue;
840 for (
const auto &arg : x.get_args()) {
842 b = andwk_tribool(b, is_rational_);
843 if (is_indeterminate(b))
848tribool RationalVisitor::apply(
const Basic &b)
851 tribool result = is_rational_;
852 if (not rational_ and not neither_) {
853 result = not_tribool(result);
858tribool is_rational(
const Basic &b)
860 RationalVisitor visitor(
true);
861 return visitor.apply(b);
864tribool is_irrational(
const Basic &b)
866 RationalVisitor visitor(
false);
867 return visitor.apply(b);
870void FiniteVisitor::error()
872 throw SymEngineException(
873 "Only numeric types allowed for is_finite/is_infinite");
876void FiniteVisitor::bvisit(
const Basic &x)
878 is_finite_ = tribool::indeterminate;
881void FiniteVisitor::bvisit(
const Symbol &x)
884 is_finite_ = assumptions_->is_complex(x.rcp_from_this());
886 is_finite_ = tribool::indeterminate;
890void FiniteVisitor::bvisit(
const Number &x)
892 is_finite_ = tribool::tritrue;
895void FiniteVisitor::bvisit(
const Infty &x)
897 is_finite_ = tribool::trifalse;
900void FiniteVisitor::bvisit(
const NaN &x)
905void FiniteVisitor::bvisit(
const Set &x)
910void FiniteVisitor::bvisit(
const Relational &x)
915void FiniteVisitor::bvisit(
const Boolean &x)
920void FiniteVisitor::bvisit(
const Constant &x)
922 is_finite_ = tribool::tritrue;
925tribool FiniteVisitor::apply(
const Basic &b)
931tribool is_finite(
const Basic &b,
const Assumptions *assumptions)
933 FiniteVisitor visitor(assumptions);
934 return visitor.apply(b);
937tribool is_infinite(
const Basic &b,
const Assumptions *assumptions)
939 FiniteVisitor visitor(assumptions);
940 return not_tribool(visitor.apply(b));
943tribool is_even(
const Basic &b,
const Assumptions *assumptions)
945 return is_integer(*
div(b.rcp_from_this(),
integer(2)), assumptions);
948tribool is_odd(
const Basic &b,
const Assumptions *assumptions)
954void AlgebraicVisitor::error()
956 throw SymEngineException(
957 "Only numeric types allowed for is_algebraic/is_transcendental");
960void AlgebraicVisitor::bvisit(
const Basic &x)
962 is_algebraic_ = tribool::indeterminate;
965void AlgebraicVisitor::bvisit(
const Set &x)
970void AlgebraicVisitor::bvisit(
const Relational &x)
975void AlgebraicVisitor::bvisit(
const Boolean &x)
980void AlgebraicVisitor::bvisit(
const Add &x)
985 tribool current = tribool::tritrue;
986 for (
const auto &arg : x.get_args()) {
988 if (is_false(current) and is_false(is_algebraic_)) {
989 is_algebraic_ = tribool::indeterminate;
992 current = andwk_tribool(current, is_algebraic_);
993 if (is_indeterminate(current)) {
994 is_algebraic_ = current;
998 is_algebraic_ = current;
1001void AlgebraicVisitor::bvisit(
const Symbol &x)
1004 is_algebraic_ = assumptions_->is_rational(x.rcp_from_this());
1005 if (is_false(is_algebraic_)) {
1006 is_algebraic_ = tribool::indeterminate;
1009 is_algebraic_ = tribool::indeterminate;
1013void AlgebraicVisitor::bvisit(
const Constant &x)
1015 if (
eq(x, *pi) or
eq(x, *E)) {
1016 is_algebraic_ = tribool::trifalse;
1017 }
else if (
eq(x, *GoldenRatio)) {
1018 is_algebraic_ = tribool::tritrue;
1022 is_algebraic_ = tribool::indeterminate;
1026void AlgebraicVisitor::bvisit(
const Integer &x)
1028 is_algebraic_ = tribool::tritrue;
1031void AlgebraicVisitor::bvisit(
const Rational &x)
1033 is_algebraic_ = tribool::tritrue;
1036void AlgebraicVisitor::trans_nonzero_and_algebraic(
const Basic &b)
1040 if (is_true(is_algebraic_) and is_true(
is_nonzero(b))) {
1041 is_algebraic_ = tribool::trifalse;
1043 is_algebraic_ = tribool::indeterminate;
1047void AlgebraicVisitor::bvisit(
const TrigFunction &x)
1050 trans_nonzero_and_algebraic(*x.get_arg());
1053void AlgebraicVisitor::bvisit(
const HyperbolicFunction &x)
1056 trans_nonzero_and_algebraic(*x.get_arg());
1059void AlgebraicVisitor::bvisit(
const LambertW &x)
1062 trans_nonzero_and_algebraic(*x.get_arg());
1065tribool AlgebraicVisitor::apply(
const Basic &b)
1068 return is_algebraic_;
1071tribool is_algebraic(
const Basic &b,
const Assumptions *assumptions)
1073 AlgebraicVisitor visitor(assumptions);
1074 return visitor.apply(b);
1077tribool is_transcendental(
const Basic &b,
const Assumptions *assumptions)
1079 AlgebraicVisitor visitor(assumptions);
1080 return not_tribool(visitor.apply(b));
The lowest unit of symbolic representation.
static RCP< const Number > from_two_nums(const Number &re, const Number &im)
Main namespace for SymEngine package.
RCP< const Basic > div(const RCP< const Basic > &a, const RCP< const Basic > &b)
Division.
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
RCP< const Basic > sub(const RCP< const Basic > &a, const RCP< const Basic > &b)
Substracts b from a.
RCP< const Basic > exp(const RCP< const Basic > &x)
Returns the natural exponential function E**x = pow(E, x)
bool is_polynomial(const Basic &b, const set_basic &variables)
Check if expression is a polynomial.
tribool is_nonzero(const Basic &b, const Assumptions *assumptions=nullptr)
Check if a number is non-zero.
RCP< const Basic > cos(const RCP< const Basic > &arg)
Canonicalize Cos:
RCP< const Basic > add(const RCP< const Basic > &a, const RCP< const Basic > &b)
Adds two objects (safely).
bool is_a_Complex(const Basic &b)
std::enable_if< std::is_integral< T >::value, RCP< constInteger > >::type integer(T i)
RCP< const Basic > sin(const RCP< const Basic > &arg)
Canonicalize Sin: