6RCP<const Boolean> Boolean::logical_not()
const
8 return make_rcp<const Not>(this->rcp_from_this_cast<const Boolean>());
11BooleanAtom::BooleanAtom(
bool b)
12 : b_{b} {SYMENGINE_ASSIGN_TYPEID()}
14 hash_t BooleanAtom::__hash__()
const
16 hash_t seed = SYMENGINE_BOOLEAN_ATOM;
21bool BooleanAtom::get_val()
const
31bool BooleanAtom::__eq__(
const Basic &o)
const
33 return is_a<BooleanAtom>(o)
34 and get_val() == down_cast<const BooleanAtom &>(o).get_val();
37int BooleanAtom::compare(
const Basic &o)
const
39 SYMENGINE_ASSERT(is_a<BooleanAtom>(o))
40 bool ob = down_cast<const BooleanAtom &>(o).get_val();
48RCP<const Boolean> BooleanAtom::logical_not()
const
50 return boolean(not this->get_val());
53#define DEFINE_CONST_BOOL(n, v) \
54 RCP<const BooleanAtom> n = []() { \
55 static const RCP<const BooleanAtom> c = make_rcp<BooleanAtom>(v); \
59DEFINE_CONST_BOOL(boolTrue,
true);
60DEFINE_CONST_BOOL(boolFalse,
false);
62#undef DEFINE_CONST_BOOL
64Contains::Contains(
const RCP<const Basic> &expr,
const RCP<const Set> &set)
65 : expr_{expr}, set_{set} {SYMENGINE_ASSIGN_TYPEID()}
69 hash_t seed = SYMENGINE_CONTAINS;
70 hash_combine<Basic>(seed, *expr_);
71 hash_combine<Basic>(seed, *set_);
75RCP<const Basic> Contains::get_expr()
const
80RCP<const Set> Contains::get_set()
const
95 return is_a<Contains>(o)
96 and unified_eq(get_expr(), down_cast<const Contains &>(o).get_expr())
97 and unified_eq(get_set(), down_cast<const Contains &>(o).get_set());
102 SYMENGINE_ASSERT(is_a<Contains>(o))
103 const Contains &c = down_cast<const Contains &>(o);
110RCP<const Basic> Contains::create(
const RCP<const Basic> &lhs,
111 const RCP<const Set> &rhs)
const
113 return contains(lhs, rhs);
116RCP<const Boolean> contains(
const RCP<const Basic> &expr,
117 const RCP<const Set> &set)
120 return set->contains(expr);
122 return make_rcp<Contains>(expr, set);
126RCP<const Basic> piecewise(
const PiecewiseVec &vec)
128 PiecewiseVec new_vec;
129 set_boolean conditions;
130 for (
auto &p : vec) {
131 if (
eq(*p.second, *boolFalse)) {
133 }
else if (
eq(*p.second, *boolTrue)) {
134 new_vec.push_back(p);
135 conditions.
insert(p.second);
137 }
else if (conditions.find(p.second) == conditions.end()) {
138 new_vec.push_back(p);
139 conditions.insert(p.second);
142 if (new_vec.size() == 0) {
143 throw DomainError(
"piecewise undefined for this domain.");
144 }
else if (new_vec.size() == 1 and
eq(*new_vec[0].second, *boolTrue)) {
145 return new_vec[0].first;
147 return make_rcp<Piecewise>(
std::move(new_vec));
152 SYMENGINE_ASSIGN_TYPEID()
153 SYMENGINE_ASSERT(is_canonical(vec_));
159 bool found_true =
false;
160 for (
auto &p : vec) {
164 if (
eq(*p.second, *boolFalse)) {
166 }
else if (
eq(*p.second, *boolTrue)) {
168 }
else if (conditions.
find(p.second) == conditions.
end()) {
169 conditions.
insert(p.second);
174 if (vec.size() == 0) {
176 }
else if (vec.size() == 1 and
eq(*vec[0].second, *boolTrue)) {
184 hash_t seed = this->get_type_code();
185 for (
auto &p : vec_) {
186 hash_combine<Basic>(seed, *p.first);
187 hash_combine<Basic>(seed, *p.second);
200 for (
auto &p : vec_) {
209 return is_a<Piecewise>(o)
210 and unified_eq(get_vec(), down_cast<const Piecewise &>(o).get_vec());
222 SYMENGINE_ASSIGN_TYPEID()
223 SYMENGINE_ASSERT(is_canonical(s));
228 hash_t seed = SYMENGINE_AND;
229 for (
const auto &a : container_)
230 hash_combine<Basic>(seed, *a);
236 vec_basic v(container_.begin(), container_.end());
243 and unified_eq(container_,
244 down_cast<const And &>(o).get_container());
249 SYMENGINE_ASSERT(is_a<And>(o))
251 down_cast<const And &>(o).get_container());
254bool And::is_canonical(
const set_boolean &container_)
256 if (container_.
size() >= 2) {
257 for (
auto &a : container_) {
258 if (is_a<BooleanAtom>(*a) or is_a<And>(*a))
260 if (container_.find(SymEngine::logical_not(a)) != container_.end())
268const set_boolean &And::get_container()
const
273RCP<const Basic> And::create(
const set_boolean &a)
const
275 return logical_and(a);
278RCP<const Boolean> And::logical_not()
const
280 auto container = this->get_container();
282 for (
auto &a : container) {
283 cont.
insert(SymEngine::logical_not(a));
285 return make_rcp<const Or>(cont);
288Or::Or(
const set_boolean &s) : container_{s}
290 SYMENGINE_ASSIGN_TYPEID()
291 SYMENGINE_ASSERT(is_canonical(s));
296 hash_t seed = SYMENGINE_OR;
297 for (
const auto &a : container_)
298 hash_combine<Basic>(seed, *a);
304 vec_basic v(container_.begin(), container_.end());
311 and unified_eq(container_, down_cast<const Or &>(o).get_container());
316 SYMENGINE_ASSERT(is_a<Or>(o))
318 down_cast<const Or &>(o).get_container());
321bool Or::is_canonical(
const set_boolean &container_)
323 if (container_.
size() >= 2) {
324 for (
auto &a : container_) {
325 if (is_a<BooleanAtom>(*a) or is_a<Or>(*a))
327 if (container_.find(SymEngine::logical_not(a)) != container_.end())
335const set_boolean &Or::get_container()
const
340RCP<const Boolean> Or::logical_not()
const
342 auto container = this->get_container();
344 for (
auto &a : container) {
345 cont.
insert(SymEngine::logical_not(a));
347 return make_rcp<const And>(cont);
350Not::Not(
const RCP<const Boolean> &in) : arg_{in}
352 SYMENGINE_ASSIGN_TYPEID()
353 SYMENGINE_ASSERT(is_canonical(in));
358 hash_t seed = SYMENGINE_NOT;
359 hash_combine<Basic>(seed, *arg_);
372 return is_a<Not>(o) and
eq(*arg_, *down_cast<const Not &>(o).get_arg());
377 SYMENGINE_ASSERT(is_a<Not>(o))
378 return arg_->__cmp__(*down_cast<const Not &>(o).get_arg());
381bool Not::is_canonical(
const RCP<const Boolean> &in)
383 if (is_a<BooleanAtom>(*in) or is_a<Not>(*in))
388RCP<const Boolean> Not::get_arg()
const
393RCP<const Boolean> Not::logical_not()
const
395 return this->get_arg();
398Xor::Xor(
const vec_boolean &s) : container_{s}
400 SYMENGINE_ASSIGN_TYPEID()
401 SYMENGINE_ASSERT(is_canonical(s));
406 hash_t seed = SYMENGINE_XOR;
407 for (
const auto &a : container_)
408 hash_combine<Basic>(seed, *a);
414 vec_basic v(container_.begin(), container_.end());
421 and unified_eq(container_,
422 down_cast<const Xor &>(o).get_container());
427 SYMENGINE_ASSERT(is_a<Xor>(o))
429 down_cast<const Xor &>(o).get_container());
432bool Xor::is_canonical(
const vec_boolean &container_)
434 if (container_.
size() >= 2) {
436 for (
auto &a : container_) {
437 if (is_a<BooleanAtom>(*a) or is_a<Xor>(*a)) {
440 if (args.
find(a) != args.
end()) {
443 if (args.
find(SymEngine::logical_not(a)) != args.
end()) {
453const vec_boolean &Xor::get_container()
const
458const vec_boolean get_vec_from_set(
const set_boolean &s)
460 vec_boolean v(s.begin(), s.end());
464template <
typename caller>
465RCP<const Boolean> and_or(
const set_boolean &s,
const bool &op_x_notx)
469 if (is_a<BooleanAtom>(*a)) {
470 auto val = down_cast<const BooleanAtom &>(*a).get_val();
471 if (val == op_x_notx)
472 return boolean(op_x_notx);
476 if (is_a<caller>(*a)) {
477 const caller &to_insert = down_cast<const caller &>(*a);
478 auto container = to_insert.get_container();
479 args.insert(container.begin(), container.end());
484 for (
auto &a : args) {
485 if (args.find(logical_not(a)) != args.end())
486 return boolean(op_x_notx);
489 for (
auto it = args.begin(); it != args.end(); it++) {
490 if (is_a<Contains>(**it)
491 and is_a<Symbol>(*down_cast<const Contains &>(**it).get_expr())
493 *down_cast<const Contains &>(**it).get_set())) {
494 auto sym = down_cast<const Contains &>(**it).get_expr();
499 auto fset = down_cast<const FiniteSet &>(
500 *down_cast<const Contains &>(**it).get_set())
505 for (
const auto &elem : fset) {
513 auto restCont = args;
515 auto restCond = logical_and(restCont);
517 bool symexists =
false;
518 for (
const auto &fselement : fset) {
520 auto contain = restCond->subs(d);
521 if (
eq(*contain, *
boolean(
true))) {
522 present.
insert(fselement);
523 }
else if (not
eq(*contain, *
boolean(
false))) {
524 present.insert(fselement);
532 return finiteset(present)->contains(sym);
533 }
else if (present.size() != fset.size()) {
534 restCond = logical_and(
535 {
finiteset(present)->contains(sym), restCond});
545 if (args.size() == 1)
546 return *(args.begin());
547 else if (args.size() == 0)
548 return boolean(not op_x_notx);
549 return make_rcp<const caller>(args);
552RCP<const Boolean> logical_not(
const RCP<const Boolean> &s)
554 return s->logical_not();
557RCP<const Boolean> logical_xor(
const vec_boolean &s)
562 if (is_a<BooleanAtom>(*a)) {
563 auto val = down_cast<const BooleanAtom &>(*a).get_val();
568 }
else if (is_a<Xor>(*a)) {
569 auto container = down_cast<const Xor &>(*a).get_container();
570 for (
auto &aa : container) {
571 if (args.find(aa) != args.end()) {
574 auto pos = args.find(logical_not(aa));
575 if (pos != args.end()) {
585 if (args.find(a) != args.end()) {
588 auto pos = args.find(logical_not(a));
589 if (pos != args.end()) {
599 if (args.size() == 0) {
601 }
else if (args.size() == 1) {
602 return *args.begin();
604 return make_rcp<const Xor>(get_vec_from_set(args));
607 if (args.size() == 0) {
609 }
else if (args.size() == 1) {
610 return logical_not(*args.begin());
612 return make_rcp<const Not>(
613 make_rcp<const Xor>(get_vec_from_set(args)));
624 const RCP<const Basic> &rhs)
const
630 if (is_a<BooleanAtom>(*lhs) and is_a<BooleanAtom>(*rhs))
635Equality::Equality(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
638 SYMENGINE_ASSIGN_TYPEID();
643 const RCP<const Basic> &rhs)
const
648RCP<const Boolean> Equality::logical_not()
const
653RCP<const Boolean>
Eq(
const RCP<const Basic> &lhs)
655 return Eq(lhs, zero);
658RCP<const Boolean>
Eq(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
660 if (is_a<NaN>(*lhs) or is_a<NaN>(*rhs))
661 return boolean(
false);
662 bool b =
eq(*lhs, *rhs);
664 return boolean(
true);
667 or (is_a<BooleanAtom>(*lhs) and is_a<BooleanAtom>(*rhs)))
668 return boolean(
false);
669 if (lhs->__cmp__(*rhs) == 1)
670 return make_rcp<const Equality>(rhs, lhs);
671 return make_rcp<Equality>(lhs, rhs);
675Unequality::Unequality(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
676 : Relational(lhs, rhs)
678 SYMENGINE_ASSIGN_TYPEID();
679 SYMENGINE_ASSERT(is_canonical(lhs, rhs));
682RCP<const Basic> Unequality::create(
const RCP<const Basic> &lhs,
683 const RCP<const Basic> &rhs)
const
688RCP<const Boolean> Unequality::logical_not()
const
690 return make_rcp<const Equality>(get_arg1(), get_arg2());
693RCP<const Boolean>
Ne(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
695 RCP<const Basic> r =
Eq(lhs, rhs);
696 if (is_a<BooleanAtom>(*r)) {
697 return logical_not(rcp_static_cast<const BooleanAtom>(r));
699 if (lhs->__cmp__(*rhs) == 1)
700 return make_rcp<const Unequality>(rhs, lhs);
701 return make_rcp<Unequality>(lhs, rhs);
704LessThan::LessThan(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
705 : Relational(lhs, rhs)
707 SYMENGINE_ASSIGN_TYPEID();
708 SYMENGINE_ASSERT(is_canonical(lhs, rhs));
711RCP<const Basic> LessThan::create(
const RCP<const Basic> &lhs,
712 const RCP<const Basic> &rhs)
const
717RCP<const Boolean> LessThan::logical_not()
const
719 return make_rcp<const StrictLessThan>(get_arg2(), get_arg1());
722RCP<const Boolean>
Le(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
725 throw SymEngineException(
"Invalid comparison of complex numbers.");
726 if (is_a<NaN>(*lhs) or is_a<NaN>(*rhs))
727 throw SymEngineException(
"Invalid NaN comparison.");
728 if (
eq(*lhs, *ComplexInf) or
eq(*rhs, *ComplexInf))
729 throw SymEngineException(
"Invalid comparison of complex zoo.");
730 if (is_a<BooleanAtom>(*lhs) or is_a<BooleanAtom>(*rhs))
731 throw SymEngineException(
"Invalid comparison of Boolean objects.");
733 return boolean(
true);
734 if (is_a_Number(*lhs) and is_a_Number(*rhs)) {
735 RCP<const Number> s = down_cast<const Number &>(*lhs).sub(
736 down_cast<const Number &>(*rhs));
737 if (s->is_negative())
738 return boolean(
true);
739 return boolean(
false);
741 return make_rcp<const LessThan>(lhs, rhs);
744RCP<const Boolean>
Ge(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
749StrictLessThan::StrictLessThan(
const RCP<const Basic> &lhs,
750 const RCP<const Basic> &rhs)
751 : Relational(lhs, rhs)
753 SYMENGINE_ASSIGN_TYPEID();
754 SYMENGINE_ASSERT(is_canonical(lhs, rhs));
757RCP<const Basic> StrictLessThan::create(
const RCP<const Basic> &lhs,
758 const RCP<const Basic> &rhs)
const
763RCP<const Boolean> StrictLessThan::logical_not()
const
765 return make_rcp<const LessThan>(get_arg2(), get_arg1());
768RCP<const Boolean>
Lt(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
771 throw SymEngineException(
"Invalid comparison of complex numbers.");
772 if (is_a<NaN>(*lhs) or is_a<NaN>(*rhs))
773 throw SymEngineException(
"Invalid NaN comparison.");
774 if (
eq(*lhs, *ComplexInf) or
eq(*rhs, *ComplexInf))
775 throw SymEngineException(
"Invalid comparison of complex zoo.");
776 if (is_a<BooleanAtom>(*lhs) or is_a<BooleanAtom>(*rhs))
777 throw SymEngineException(
"Invalid comparison of Boolean objects.");
779 return boolean(
false);
780 if (is_a_Number(*lhs) and is_a_Number(*rhs)) {
781 RCP<const Number> s = down_cast<const Number &>(*lhs).sub(
782 down_cast<const Number &>(*rhs));
783 if (s->is_negative())
784 return boolean(
true);
785 return boolean(
false);
787 return make_rcp<const StrictLessThan>(lhs, rhs);
790RCP<const Boolean>
Gt(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
795RCP<const Boolean> logical_and(
const set_boolean &s)
797 return and_or<And>(s,
false);
800RCP<const Boolean> logical_nand(
const set_boolean &s)
802 RCP<const Boolean> a = logical_and(s);
803 return logical_not(a);
806RCP<const Boolean> logical_or(
const set_boolean &s)
808 return and_or<Or>(s,
true);
811RCP<const Boolean> logical_nor(
const set_boolean &s)
813 return logical_not(and_or<Or>(s,
true));
816RCP<const Boolean> logical_xnor(
const vec_boolean &s)
818 return logical_not(logical_xor(s));
hash_t __hash__() const override
bool __eq__(const Basic &o) const override
Test equality.
int compare(const Basic &o) const override
Structural equality comparator.
vec_basic get_args() const override
Returns the list of arguments.
The lowest unit of symbolic representation.
bool __eq__(const Basic &o) const override
Test equality.
int compare(const Basic &o) const override
Structural equality comparator.
vec_basic get_args() const override
Returns the list of arguments.
hash_t __hash__() const override
RCP< const T2 > rcp_from_this_cast() const
Get RCP<T2> pointer to self (it will cast the pointer to T2)
RCP< const Basic > create(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs) const override
Method to construct classes with canonicalization.
vec_basic get_args() const override
Returns the list of arguments.
int compare(const Basic &o) const override
Structural equality comparator.
hash_t __hash__() const override
bool __eq__(const Basic &o) const override
Test equality.
vec_basic get_args() const override
Returns the list of arguments.
hash_t __hash__() const override
bool __eq__(const Basic &o) const override
Test equality.
int compare(const Basic &o) const override
Structural equality comparator.
vec_basic get_args() const override
Returns the list of arguments.
Piecewise(PiecewiseVec &&vec)
Constructor.
bool __eq__(const Basic &o) const override
Test equality.
int compare(const Basic &o) const override
Structural equality comparator.
hash_t __hash__() const override
Relational(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Constructor.
virtual bool is_canonical(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs) const
RCP< const Basic > get_arg2() const
RCP< const Basic > get_arg1() const
bool __eq__(const Basic &o) const override
Test equality.
int compare(const Basic &o) const override
vec_basic get_args() const override
Returns the list of arguments.
Main namespace for SymEngine package.
bool is_a_Number(const Basic &b)
RCP< const Boolean > Ge(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Convenience function returning LessThan object.
RCP< const Set > finiteset(const set_basic &container)
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
RCP< const Boolean > Lt(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Returns the canonicalized StrictLessThan object from the arguments.
RCP< const Boolean > Le(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Returns the canonicalized LessThan object from the arguments.
bool is_same_type(const Basic &a, const Basic &b)
Returns true if a and b are exactly the same type T.
RCP< const Boolean > Eq(const RCP< const Basic > &lhs)
Returns the canonicalized Equality object from a single argument.
int unified_compare(const T &a, const T &b)
bool is_a_Complex(const Basic &b)
RCP< const Boolean > Gt(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Convenience function returning StrictLessThan object.
RCP< const Boolean > Ne(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Returns the canonicalized Unequality object from the arguments.