1 #include <symengine/test_visitors.h>
6 void ZeroVisitor::error()
8 throw SymEngineException(
9 "Only numeric types allowed for is_zero/is_nonzero");
12 void ZeroVisitor::bvisit(
const Basic &x)
14 is_zero_ = tribool::indeterminate;
17 void ZeroVisitor::bvisit(
const Set &x)
22 void ZeroVisitor::bvisit(
const Relational &x)
27 void ZeroVisitor::bvisit(
const Boolean &x)
32 void ZeroVisitor::bvisit(
const Constant &x)
34 is_zero_ = tribool::trifalse;
37 void ZeroVisitor::bvisit(
const Abs &x)
39 x.get_arg()->accept(*
this);
42 void ZeroVisitor::bvisit(
const Conjugate &x)
44 x.get_arg()->accept(*
this);
47 void ZeroVisitor::bvisit(
const Sign &x)
49 x.get_arg()->accept(*
this);
52 void ZeroVisitor::bvisit(
const PrimePi &x)
55 is_zero_ = is_negative(*
sub(x.get_arg(),
integer(2)));
58 void ZeroVisitor::bvisit(
const Number &x)
60 if (
bool(x.is_zero())) {
61 is_zero_ = tribool::tritrue;
63 is_zero_ = tribool::trifalse;
67 void ZeroVisitor::bvisit(
const Symbol &x)
70 is_zero_ = assumptions_->is_zero(x.rcp_from_this());
72 is_zero_ = tribool::indeterminate;
76 tribool ZeroVisitor::apply(
const Basic &b)
85 return visitor.apply(b);
91 return not_tribool(visitor.apply(b));
94 void PositiveVisitor::error()
96 throw SymEngineException(
"Only numeric types allowed for is_positive");
99 void PositiveVisitor::bvisit(
const Constant &x)
101 is_positive_ = tribool::tritrue;
104 void PositiveVisitor::bvisit(
const Basic &x)
106 is_positive_ = tribool::indeterminate;
109 void PositiveVisitor::bvisit(
const Set &x)
114 void PositiveVisitor::bvisit(
const Relational &x)
119 void PositiveVisitor::bvisit(
const Boolean &x)
124 void PositiveVisitor::bvisit(
const Symbol &x)
127 is_positive_ = assumptions_->is_positive(x.rcp_from_this());
129 is_positive_ = tribool::indeterminate;
133 void 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;
144 void 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;
189 tribool PositiveVisitor::apply(
const Basic &b)
195 tribool is_positive(
const Basic &b,
const Assumptions *assumptions)
197 PositiveVisitor visitor(assumptions);
198 return visitor.apply(b);
201 void NonPositiveVisitor::error()
203 throw SymEngineException(
"Only numeric types allowed for is_negative");
206 void NonPositiveVisitor::bvisit(
const Constant &x)
208 is_nonpositive_ = tribool::trifalse;
211 void NonPositiveVisitor::bvisit(
const Basic &x)
213 is_nonpositive_ = tribool::indeterminate;
216 void NonPositiveVisitor::bvisit(
const Set &x)
221 void NonPositiveVisitor::bvisit(
const Relational &x)
226 void NonPositiveVisitor::bvisit(
const Boolean &x)
231 void NonPositiveVisitor::bvisit(
const Symbol &x)
234 is_nonpositive_ = assumptions_->is_nonpositive(x.rcp_from_this());
236 is_nonpositive_ = tribool::indeterminate;
240 void 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;
251 tribool NonPositiveVisitor::apply(
const Basic &b)
254 return is_nonpositive_;
257 tribool is_nonpositive(
const Basic &b,
const Assumptions *assumptions)
259 NonPositiveVisitor visitor(assumptions);
260 return visitor.apply(b);
263 void NegativeVisitor::error()
265 throw SymEngineException(
"Only numeric types allowed for is_negative");
268 void NegativeVisitor::bvisit(
const Basic &x)
270 is_negative_ = tribool::indeterminate;
273 void NegativeVisitor::bvisit(
const Set &x)
278 void NegativeVisitor::bvisit(
const Relational &x)
283 void NegativeVisitor::bvisit(
const Boolean &x)
288 void NegativeVisitor::bvisit(
const Constant &x)
290 is_negative_ = tribool::trifalse;
293 void NegativeVisitor::bvisit(
const Symbol &x)
296 is_negative_ = assumptions_->is_negative(x.rcp_from_this());
298 is_negative_ = tribool::indeterminate;
302 void 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;
313 tribool NegativeVisitor::apply(
const Basic &b)
319 tribool is_negative(
const Basic &b,
const Assumptions *assumptions)
321 NegativeVisitor visitor(assumptions);
322 return visitor.apply(b);
325 void NonNegativeVisitor::error()
327 throw SymEngineException(
"Only numeric types allowed for is_nonnegative");
330 void NonNegativeVisitor::bvisit(
const Basic &x)
332 is_nonnegative_ = tribool::indeterminate;
335 void NonNegativeVisitor::bvisit(
const Set &x)
340 void NonNegativeVisitor::bvisit(
const Relational &x)
345 void NonNegativeVisitor::bvisit(
const Boolean &x)
350 void NonNegativeVisitor::bvisit(
const Constant &x)
352 is_nonnegative_ = tribool::tritrue;
355 void NonNegativeVisitor::bvisit(
const Symbol &x)
358 is_nonnegative_ = assumptions_->is_nonnegative(x.rcp_from_this());
360 is_nonnegative_ = tribool::indeterminate;
364 void 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;
375 tribool NonNegativeVisitor::apply(
const Basic &b)
378 return is_nonnegative_;
381 tribool is_nonnegative(
const Basic &b,
const Assumptions *assumptions)
383 NonNegativeVisitor visitor(assumptions);
384 return visitor.apply(b);
387 void IntegerVisitor::bvisit(
const Symbol &x)
390 is_integer_ = assumptions_->is_integer(x.rcp_from_this());
392 is_integer_ = tribool::indeterminate;
396 void 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;
406 void 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;
417 void 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;
428 tribool IntegerVisitor::apply(
const Basic &b)
434 tribool is_integer(
const Basic &b,
const Assumptions *assumptions)
436 IntegerVisitor visitor(assumptions);
437 return visitor.apply(b);
440 void RealVisitor::bvisit(
const Symbol &x)
443 is_real_ = assumptions_->is_real(x.rcp_from_this());
445 is_real_ = tribool::indeterminate;
449 void 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;
458 void 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;
468 void 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)) {
481 void 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;
512 void 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;
541 void RealVisitor::bvisit(
const Pow &x)
543 this->check_power(x.get_base(), x.get_exp());
546 tribool RealVisitor::apply(
const Basic &b)
552 tribool is_real(
const Basic &b,
const Assumptions *assumptions)
554 RealVisitor visitor(assumptions);
555 return visitor.apply(b);
558 void ComplexVisitor::bvisit(
const Symbol &x)
561 is_complex_ = assumptions_->is_complex(x.rcp_from_this());
563 is_complex_ = tribool::indeterminate;
567 void 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;
576 void 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))
587 void 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))
598 void ComplexVisitor::check_power(
const Basic &base,
const Basic &
exp)
601 if (is_true(is_complex_)) {
606 void ComplexVisitor::bvisit(
const Pow &x)
608 check_power(*x.get_base(), *x.get_exp());
611 void ComplexVisitor::bvisit(
const Log &x)
613 complex_arg_not_zero(x, *x.get_arg());
616 void ComplexVisitor::bvisit(
const Tan &x)
618 complex_arg_not_zero(x, *
cos(x.get_arg()));
621 void 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);
634 void 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);
660 void ComplexVisitor::bvisit(
const ATan &x)
662 complex_arg_not_pm(x,
false);
665 void ComplexVisitor::bvisit(
const ATanh &x)
667 complex_arg_not_pm(x,
true);
670 void ComplexVisitor::bvisit(
const ACot &x)
672 complex_arg_not_pm(x,
false);
675 void ComplexVisitor::bvisit(
const ACoth &x)
677 complex_arg_not_pm(x,
true);
680 void ComplexVisitor::bvisit(
const Cot &x)
682 complex_arg_not_zero(x, *
sin(x.get_arg()));
685 void ComplexVisitor::bvisit(
const Sec &x)
687 complex_arg_not_zero(x, *
cos(x.get_arg()));
690 void ComplexVisitor::bvisit(
const ASec &x)
692 complex_arg_not_zero(x, *x.get_arg());
695 void ComplexVisitor::bvisit(
const ASech &x)
697 complex_arg_not_zero(x, *x.get_arg());
700 void ComplexVisitor::bvisit(
const Csc &x)
702 complex_arg_not_zero(x, *
sin(x.get_arg()));
705 void ComplexVisitor::bvisit(
const ACsc &x)
707 complex_arg_not_zero(x, *x.get_arg());
710 void ComplexVisitor::bvisit(
const ACsch &x)
712 complex_arg_not_zero(x, *x.get_arg());
715 tribool ComplexVisitor::apply(
const Basic &b)
721 tribool is_complex(
const Basic &b,
const Assumptions *assumptions)
723 ComplexVisitor visitor(assumptions);
724 return visitor.apply(b);
727 void 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;
741 void PolynomialVisitor::bvisit(
const Add &x)
743 for (
const auto &arg : x.get_args()) {
750 void PolynomialVisitor::bvisit(
const Mul &x)
752 for (
const auto &p : x.get_dict()) {
753 this->check_power(*p.first, *p.second);
759 void 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();
784 void PolynomialVisitor::bvisit(
const Pow &x)
786 check_power(*x.get_base(), *x.get_exp());
789 void 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;
806 bool PolynomialVisitor::apply(
const Basic &b)
809 return is_polynomial_;
815 return visitor.apply(b);
818 void 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)) {
826 void 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;
837 void 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))
848 tribool RationalVisitor::apply(
const Basic &b)
851 tribool result = is_rational_;
852 if (not rational_ and not neither_) {
853 result = not_tribool(result);
858 tribool is_rational(
const Basic &b)
860 RationalVisitor visitor(
true);
861 return visitor.apply(b);
864 tribool is_irrational(
const Basic &b)
866 RationalVisitor visitor(
false);
867 return visitor.apply(b);
870 void FiniteVisitor::error()
872 throw SymEngineException(
873 "Only numeric types allowed for is_finite/is_infinite");
876 void FiniteVisitor::bvisit(
const Basic &x)
878 is_finite_ = tribool::indeterminate;
881 void FiniteVisitor::bvisit(
const Symbol &x)
884 is_finite_ = assumptions_->is_complex(x.rcp_from_this());
886 is_finite_ = tribool::indeterminate;
890 void FiniteVisitor::bvisit(
const Number &x)
892 is_finite_ = tribool::tritrue;
895 void FiniteVisitor::bvisit(
const Infty &x)
897 is_finite_ = tribool::trifalse;
900 void FiniteVisitor::bvisit(
const NaN &x)
905 void FiniteVisitor::bvisit(
const Set &x)
910 void FiniteVisitor::bvisit(
const Relational &x)
915 void FiniteVisitor::bvisit(
const Boolean &x)
920 void FiniteVisitor::bvisit(
const Constant &x)
922 is_finite_ = tribool::tritrue;
925 tribool FiniteVisitor::apply(
const Basic &b)
931 tribool is_finite(
const Basic &b,
const Assumptions *assumptions)
933 FiniteVisitor visitor(assumptions);
934 return visitor.apply(b);
937 tribool is_infinite(
const Basic &b,
const Assumptions *assumptions)
939 FiniteVisitor visitor(assumptions);
940 return not_tribool(visitor.apply(b));
943 tribool is_even(
const Basic &b,
const Assumptions *assumptions)
945 return is_integer(*
div(b.rcp_from_this(),
integer(2)), assumptions);
948 tribool is_odd(
const Basic &b,
const Assumptions *assumptions)
954 void AlgebraicVisitor::error()
956 throw SymEngineException(
957 "Only numeric types allowed for is_algebraic/is_transcendental");
960 void AlgebraicVisitor::bvisit(
const Basic &x)
962 is_algebraic_ = tribool::indeterminate;
965 void AlgebraicVisitor::bvisit(
const Set &x)
970 void AlgebraicVisitor::bvisit(
const Relational &x)
975 void AlgebraicVisitor::bvisit(
const Boolean &x)
980 void 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;
1001 void 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;
1013 void 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;
1026 void AlgebraicVisitor::bvisit(
const Integer &x)
1028 is_algebraic_ = tribool::tritrue;
1031 void AlgebraicVisitor::bvisit(
const Rational &x)
1033 is_algebraic_ = tribool::tritrue;
1036 void 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;
1047 void AlgebraicVisitor::bvisit(
const TrigFunction &x)
1050 trans_nonzero_and_algebraic(*x.get_arg());
1053 void AlgebraicVisitor::bvisit(
const HyperbolicFunction &x)
1056 trans_nonzero_and_algebraic(*x.get_arg());
1059 void AlgebraicVisitor::bvisit(
const LambertW &x)
1062 trans_nonzero_and_algebraic(*x.get_arg());
1065 tribool AlgebraicVisitor::apply(
const Basic &b)
1068 return is_algebraic_;
1071 tribool is_algebraic(
const Basic &b,
const Assumptions *assumptions)
1073 AlgebraicVisitor visitor(assumptions);
1074 return visitor.apply(b);
1077 tribool 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.
std::enable_if< std::is_integral< T >::value, RCP< const Integer > >::type integer(T i)
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)
RCP< const Basic > sin(const RCP< const Basic > &arg)
Canonicalize Sin: