6 RCP<const Boolean> Boolean::logical_not()
const
8 return make_rcp<const Not>(this->rcp_from_this_cast<const Boolean>());
11 BooleanAtom::BooleanAtom(
bool b)
12 : b_{b} {SYMENGINE_ASSIGN_TYPEID()}
14 hash_t BooleanAtom::__hash__()
const
16 hash_t seed = SYMENGINE_BOOLEAN_ATOM;
21 bool BooleanAtom::get_val()
const
31 bool BooleanAtom::__eq__(
const Basic &o)
const
33 return is_a<BooleanAtom>(o)
34 and get_val() == down_cast<const BooleanAtom &>(o).get_val();
37 int BooleanAtom::compare(
const Basic &o)
const
39 SYMENGINE_ASSERT(is_a<BooleanAtom>(o))
40 bool ob = down_cast<const BooleanAtom &>(o).get_val();
48 RCP<const Boolean> BooleanAtom::logical_not()
const
50 return boolean(not this->get_val());
53 Contains::Contains(
const RCP<const Basic> &expr,
const RCP<const Set> &set)
54 : expr_{expr}, set_{set} {SYMENGINE_ASSIGN_TYPEID()}
58 hash_t seed = SYMENGINE_CONTAINS;
59 hash_combine<Basic>(seed, *expr_);
60 hash_combine<Basic>(seed, *set_);
64 RCP<const Basic> Contains::get_expr()
const
69 RCP<const Set> Contains::get_set()
const
84 return is_a<Contains>(o)
85 and unified_eq(get_expr(), down_cast<const Contains &>(o).get_expr())
86 and unified_eq(get_set(), down_cast<const Contains &>(o).get_set());
91 SYMENGINE_ASSERT(is_a<Contains>(o))
92 const Contains &c = down_cast<const Contains &>(o);
99 RCP<const Basic> Contains::create(
const RCP<const Basic> &lhs,
100 const RCP<const Set> &rhs)
const
102 return contains(lhs, rhs);
105 RCP<const Boolean> contains(
const RCP<const Basic> &expr,
106 const RCP<const Set> &set)
109 return set->contains(expr);
111 return make_rcp<Contains>(expr, set);
115 RCP<const Basic> piecewise(
const PiecewiseVec &vec)
117 PiecewiseVec new_vec;
118 set_boolean conditions;
119 for (
auto &p : vec) {
120 if (
eq(*p.second, *boolFalse)) {
122 }
else if (
eq(*p.second, *boolTrue)) {
123 new_vec.push_back(p);
124 conditions.
insert(p.second);
126 }
else if (conditions.find(p.second) == conditions.end()) {
127 new_vec.push_back(p);
128 conditions.insert(p.second);
131 if (new_vec.size() == 0) {
132 throw DomainError(
"piecewise undefined for this domain.");
133 }
else if (new_vec.size() == 1 and
eq(*new_vec[0].second, *boolTrue)) {
134 return new_vec[0].first;
136 return make_rcp<Piecewise>(
std::move(new_vec));
141 SYMENGINE_ASSIGN_TYPEID()
142 SYMENGINE_ASSERT(is_canonical(vec_));
148 bool found_true =
false;
149 for (
auto &p : vec) {
153 if (
eq(*p.second, *boolFalse)) {
155 }
else if (
eq(*p.second, *boolTrue)) {
157 }
else if (conditions.
find(p.second) == conditions.
end()) {
158 conditions.
insert(p.second);
163 if (vec.size() == 0) {
165 }
else if (vec.size() == 1 and
eq(*vec[0].second, *boolTrue)) {
173 hash_t seed = this->get_type_code();
174 for (
auto &p : vec_) {
175 hash_combine<Basic>(seed, *p.first);
176 hash_combine<Basic>(seed, *p.second);
189 for (
auto &p : vec_) {
198 return is_a<Piecewise>(o)
199 and unified_eq(get_vec(), down_cast<const Piecewise &>(o).get_vec());
211 SYMENGINE_ASSIGN_TYPEID()
212 SYMENGINE_ASSERT(is_canonical(s));
217 hash_t seed = SYMENGINE_AND;
218 for (
const auto &a : container_)
219 hash_combine<Basic>(seed, *a);
225 vec_basic v(container_.begin(), container_.end());
232 and unified_eq(container_,
233 down_cast<const And &>(o).get_container());
238 SYMENGINE_ASSERT(is_a<And>(o))
240 down_cast<const And &>(o).get_container());
243 bool And::is_canonical(
const set_boolean &container_)
245 if (container_.
size() >= 2) {
246 for (
auto &a : container_) {
247 if (is_a<BooleanAtom>(*a) or is_a<And>(*a))
249 if (container_.find(SymEngine::logical_not(a)) != container_.end())
257 const set_boolean &And::get_container()
const
262 RCP<const Basic> And::create(
const set_boolean &a)
const
264 return logical_and(a);
267 RCP<const Boolean> And::logical_not()
const
269 auto container = this->get_container();
271 for (
auto &a : container) {
272 cont.
insert(SymEngine::logical_not(a));
274 return make_rcp<const Or>(cont);
277 Or::Or(
const set_boolean &s) : container_{s}
279 SYMENGINE_ASSIGN_TYPEID()
280 SYMENGINE_ASSERT(is_canonical(s));
285 hash_t seed = SYMENGINE_OR;
286 for (
const auto &a : container_)
287 hash_combine<Basic>(seed, *a);
293 vec_basic v(container_.begin(), container_.end());
300 and unified_eq(container_, down_cast<const Or &>(o).get_container());
305 SYMENGINE_ASSERT(is_a<Or>(o))
307 down_cast<const Or &>(o).get_container());
310 bool Or::is_canonical(
const set_boolean &container_)
312 if (container_.
size() >= 2) {
313 for (
auto &a : container_) {
314 if (is_a<BooleanAtom>(*a) or is_a<Or>(*a))
316 if (container_.find(SymEngine::logical_not(a)) != container_.end())
324 const set_boolean &Or::get_container()
const
329 RCP<const Boolean> Or::logical_not()
const
331 auto container = this->get_container();
333 for (
auto &a : container) {
334 cont.
insert(SymEngine::logical_not(a));
336 return make_rcp<const And>(cont);
339 Not::Not(
const RCP<const Boolean> &in) : arg_{in}
341 SYMENGINE_ASSIGN_TYPEID()
342 SYMENGINE_ASSERT(is_canonical(in));
347 hash_t seed = SYMENGINE_NOT;
348 hash_combine<Basic>(seed, *arg_);
361 return is_a<Not>(o) and
eq(*arg_, *down_cast<const Not &>(o).get_arg());
366 SYMENGINE_ASSERT(is_a<Not>(o))
367 return arg_->__cmp__(*down_cast<const Not &>(o).get_arg());
370 bool Not::is_canonical(
const RCP<const Boolean> &in)
372 if (is_a<BooleanAtom>(*in) or is_a<Not>(*in))
377 RCP<const Boolean> Not::get_arg()
const
382 RCP<const Boolean> Not::logical_not()
const
384 return this->get_arg();
387 Xor::Xor(
const vec_boolean &s) : container_{s}
389 SYMENGINE_ASSIGN_TYPEID()
390 SYMENGINE_ASSERT(is_canonical(s));
395 hash_t seed = SYMENGINE_XOR;
396 for (
const auto &a : container_)
397 hash_combine<Basic>(seed, *a);
403 vec_basic v(container_.begin(), container_.end());
410 and unified_eq(container_,
411 down_cast<const Xor &>(o).get_container());
416 SYMENGINE_ASSERT(is_a<Xor>(o))
418 down_cast<const Xor &>(o).get_container());
421 bool Xor::is_canonical(
const vec_boolean &container_)
423 if (container_.
size() >= 2) {
425 for (
auto &a : container_) {
426 if (is_a<BooleanAtom>(*a) or is_a<Xor>(*a)) {
429 if (args.
find(a) != args.
end()) {
432 if (args.
find(SymEngine::logical_not(a)) != args.
end()) {
442 const vec_boolean &Xor::get_container()
const
447 const vec_boolean get_vec_from_set(
const set_boolean &s)
449 vec_boolean v(s.begin(), s.end());
453 template <
typename caller>
454 RCP<const Boolean> and_or(
const set_boolean &s,
const bool &op_x_notx)
458 if (is_a<BooleanAtom>(*a)) {
459 auto val = down_cast<const BooleanAtom &>(*a).get_val();
460 if (val == op_x_notx)
461 return boolean(op_x_notx);
465 if (is_a<caller>(*a)) {
466 const caller &to_insert = down_cast<const caller &>(*a);
467 auto container = to_insert.get_container();
468 args.insert(container.begin(), container.end());
473 for (
auto &a : args) {
474 if (args.find(logical_not(a)) != args.end())
475 return boolean(op_x_notx);
478 for (
auto it = args.begin(); it != args.end(); it++) {
479 if (is_a<Contains>(**it)
480 and is_a<Symbol>(*down_cast<const Contains &>(**it).get_expr())
482 *down_cast<const Contains &>(**it).get_set())) {
483 auto sym = down_cast<const Contains &>(**it).get_expr();
488 auto fset = down_cast<const FiniteSet &>(
489 *down_cast<const Contains &>(**it).get_set())
494 for (
const auto &elem : fset) {
502 auto restCont = args;
504 auto restCond = logical_and(restCont);
506 bool symexists =
false;
507 for (
const auto &fselement : fset) {
509 auto contain = restCond->subs(d);
510 if (
eq(*contain, *
boolean(
true))) {
511 present.
insert(fselement);
512 }
else if (not
eq(*contain, *
boolean(
false))) {
513 present.insert(fselement);
521 return finiteset(present)->contains(sym);
522 }
else if (present.size() != fset.size()) {
523 restCond = logical_and(
524 {
finiteset(present)->contains(sym), restCond});
534 if (args.size() == 1)
535 return *(args.begin());
536 else if (args.size() == 0)
537 return boolean(not op_x_notx);
538 return make_rcp<const caller>(args);
541 RCP<const Boolean> logical_not(
const RCP<const Boolean> &s)
543 return s->logical_not();
546 RCP<const Boolean> logical_xor(
const vec_boolean &s)
551 if (is_a<BooleanAtom>(*a)) {
552 auto val = down_cast<const BooleanAtom &>(*a).get_val();
557 }
else if (is_a<Xor>(*a)) {
558 auto container = down_cast<const Xor &>(*a).get_container();
559 for (
auto &aa : container) {
560 if (args.find(aa) != args.end()) {
563 auto pos = args.find(logical_not(aa));
564 if (pos != args.end()) {
574 if (args.find(a) != args.end()) {
577 auto pos = args.find(logical_not(a));
578 if (pos != args.end()) {
588 if (args.size() == 0) {
590 }
else if (args.size() == 1) {
591 return *args.begin();
593 return make_rcp<const Xor>(get_vec_from_set(args));
596 if (args.size() == 0) {
598 }
else if (args.size() == 1) {
599 return logical_not(*args.begin());
601 return make_rcp<const Not>(
602 make_rcp<const Xor>(get_vec_from_set(args)));
613 const RCP<const Basic> &rhs)
const
619 if (is_a<BooleanAtom>(*lhs) and is_a<BooleanAtom>(*rhs))
624 Equality::Equality(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
627 SYMENGINE_ASSIGN_TYPEID();
632 const RCP<const Basic> &rhs)
const
637 RCP<const Boolean> Equality::logical_not()
const
642 RCP<const Boolean>
Eq(
const RCP<const Basic> &lhs)
644 return Eq(lhs, zero);
647 RCP<const Boolean>
Eq(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
649 if (is_a<NaN>(*lhs) or is_a<NaN>(*rhs))
650 return boolean(
false);
651 bool b =
eq(*lhs, *rhs);
653 return boolean(
true);
656 or (is_a<BooleanAtom>(*lhs) and is_a<BooleanAtom>(*rhs)))
657 return boolean(
false);
658 if (lhs->__cmp__(*rhs) == 1)
659 return make_rcp<const Equality>(rhs, lhs);
660 return make_rcp<Equality>(lhs, rhs);
664 Unequality::Unequality(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
665 : Relational(lhs, rhs)
667 SYMENGINE_ASSIGN_TYPEID();
668 SYMENGINE_ASSERT(is_canonical(lhs, rhs));
671 RCP<const Basic> Unequality::create(
const RCP<const Basic> &lhs,
672 const RCP<const Basic> &rhs)
const
677 RCP<const Boolean> Unequality::logical_not()
const
679 return make_rcp<const Equality>(get_arg1(), get_arg2());
682 RCP<const Boolean>
Ne(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
684 RCP<const Basic> r =
Eq(lhs, rhs);
685 if (is_a<BooleanAtom>(*r)) {
686 return logical_not(rcp_static_cast<const BooleanAtom>(r));
688 if (lhs->__cmp__(*rhs) == 1)
689 return make_rcp<const Unequality>(rhs, lhs);
690 return make_rcp<Unequality>(lhs, rhs);
693 LessThan::LessThan(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
694 : Relational(lhs, rhs)
696 SYMENGINE_ASSIGN_TYPEID();
697 SYMENGINE_ASSERT(is_canonical(lhs, rhs));
700 RCP<const Basic> LessThan::create(
const RCP<const Basic> &lhs,
701 const RCP<const Basic> &rhs)
const
706 RCP<const Boolean> LessThan::logical_not()
const
708 return make_rcp<const StrictLessThan>(get_arg2(), get_arg1());
711 RCP<const Boolean>
Le(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
714 throw SymEngineException(
"Invalid comparison of complex numbers.");
715 if (is_a<NaN>(*lhs) or is_a<NaN>(*rhs))
716 throw SymEngineException(
"Invalid NaN comparison.");
717 if (
eq(*lhs, *ComplexInf) or
eq(*rhs, *ComplexInf))
718 throw SymEngineException(
"Invalid comparison of complex zoo.");
719 if (is_a<BooleanAtom>(*lhs) or is_a<BooleanAtom>(*rhs))
720 throw SymEngineException(
"Invalid comparison of Boolean objects.");
722 return boolean(
true);
724 RCP<const Number> s = down_cast<const Number &>(*lhs).sub(
725 down_cast<const Number &>(*rhs));
726 if (s->is_negative())
727 return boolean(
true);
728 return boolean(
false);
730 return make_rcp<const LessThan>(lhs, rhs);
733 RCP<const Boolean>
Ge(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
738 StrictLessThan::StrictLessThan(
const RCP<const Basic> &lhs,
739 const RCP<const Basic> &rhs)
740 : Relational(lhs, rhs)
742 SYMENGINE_ASSIGN_TYPEID();
743 SYMENGINE_ASSERT(is_canonical(lhs, rhs));
746 RCP<const Basic> StrictLessThan::create(
const RCP<const Basic> &lhs,
747 const RCP<const Basic> &rhs)
const
752 RCP<const Boolean> StrictLessThan::logical_not()
const
754 return make_rcp<const LessThan>(get_arg2(), get_arg1());
757 RCP<const Boolean>
Lt(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
760 throw SymEngineException(
"Invalid comparison of complex numbers.");
761 if (is_a<NaN>(*lhs) or is_a<NaN>(*rhs))
762 throw SymEngineException(
"Invalid NaN comparison.");
763 if (
eq(*lhs, *ComplexInf) or
eq(*rhs, *ComplexInf))
764 throw SymEngineException(
"Invalid comparison of complex zoo.");
765 if (is_a<BooleanAtom>(*lhs) or is_a<BooleanAtom>(*rhs))
766 throw SymEngineException(
"Invalid comparison of Boolean objects.");
768 return boolean(
false);
770 RCP<const Number> s = down_cast<const Number &>(*lhs).sub(
771 down_cast<const Number &>(*rhs));
772 if (s->is_negative())
773 return boolean(
true);
774 return boolean(
false);
776 return make_rcp<const StrictLessThan>(lhs, rhs);
779 RCP<const Boolean>
Gt(
const RCP<const Basic> &lhs,
const RCP<const Basic> &rhs)
784 RCP<const Boolean> logical_and(
const set_boolean &s)
786 return and_or<And>(s,
false);
789 RCP<const Boolean> logical_nand(
const set_boolean &s)
791 RCP<const Boolean> a = logical_and(s);
792 return logical_not(a);
795 RCP<const Boolean> logical_or(
const set_boolean &s)
797 return and_or<Or>(s,
true);
800 RCP<const Boolean> logical_nor(
const set_boolean &s)
802 return logical_not(and_or<Or>(s,
true));
805 RCP<const Boolean> logical_xnor(
const vec_boolean &s)
807 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_arg1() const
RCP< const Basic > get_arg2() 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.
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.
RCP< const Set > finiteset(const set_basic &container)
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.