Loading...
Searching...
No Matches
logic.cpp
1#include <symengine/logic.h>
2
3namespace SymEngine
4{
5
6RCP<const Boolean> Boolean::logical_not() const
7{
8 return make_rcp<const Not>(this->rcp_from_this_cast<const Boolean>());
9}
10
11BooleanAtom::BooleanAtom(bool b)
12 : b_{b} {SYMENGINE_ASSIGN_TYPEID()}
13
14 hash_t BooleanAtom::__hash__() const
15{
16 hash_t seed = SYMENGINE_BOOLEAN_ATOM;
17 if (b_)
18 ++seed;
19 return seed;
20}
21bool BooleanAtom::get_val() const
22{
23 return b_;
24}
25
26vec_basic BooleanAtom::get_args() const
27{
28 return {};
29}
30
31bool BooleanAtom::__eq__(const Basic &o) const
32{
33 return is_a<BooleanAtom>(o)
34 and get_val() == down_cast<const BooleanAtom &>(o).get_val();
35}
36
37int BooleanAtom::compare(const Basic &o) const
38{
39 SYMENGINE_ASSERT(is_a<BooleanAtom>(o))
40 bool ob = down_cast<const BooleanAtom &>(o).get_val();
41 if (get_val()) {
42 return (ob) ? 0 : 1;
43 } else {
44 return (ob) ? -1 : 0;
45 }
46}
47
48RCP<const Boolean> BooleanAtom::logical_not() const
49{
50 return boolean(not this->get_val());
51}
52
53#define DEFINE_CONST_BOOL(n, v) \
54 RCP<const BooleanAtom> n = []() { \
55 static const RCP<const BooleanAtom> c = make_rcp<BooleanAtom>(v); \
56 return c; \
57 }()
58
59DEFINE_CONST_BOOL(boolTrue, true);
60DEFINE_CONST_BOOL(boolFalse, false);
61
62#undef DEFINE_CONST_BOOL
63
64Contains::Contains(const RCP<const Basic> &expr, const RCP<const Set> &set)
65 : expr_{expr}, set_{set} {SYMENGINE_ASSIGN_TYPEID()}
66
67 hash_t Contains::__hash__() const
68{
69 hash_t seed = SYMENGINE_CONTAINS;
70 hash_combine<Basic>(seed, *expr_);
71 hash_combine<Basic>(seed, *set_);
72 return seed;
73}
74
75RCP<const Basic> Contains::get_expr() const
76{
77 return expr_;
78}
79
80RCP<const Set> Contains::get_set() const
81{
82 return set_;
83}
84
86{
87 vec_basic v;
88 v.push_back(expr_);
89 v.push_back(set_);
90 return v;
91}
92
93bool Contains::__eq__(const Basic &o) const
94{
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());
98}
99
100int Contains::compare(const Basic &o) const
101{
102 SYMENGINE_ASSERT(is_a<Contains>(o))
103 const Contains &c = down_cast<const Contains &>(o);
104 int cmp = unified_compare(get_expr(), c.get_expr());
105 if (cmp != 0)
106 return cmp;
107 return unified_compare(get_set(), c.get_set());
108}
109
110RCP<const Basic> Contains::create(const RCP<const Basic> &lhs,
111 const RCP<const Set> &rhs) const
112{
113 return contains(lhs, rhs);
114}
115
116RCP<const Boolean> contains(const RCP<const Basic> &expr,
117 const RCP<const Set> &set)
118{
119 if (is_a_Number(*expr) or is_a_Set(*expr)) {
120 return set->contains(expr);
121 } else {
122 return make_rcp<Contains>(expr, set);
123 }
124}
125
126RCP<const Basic> piecewise(const PiecewiseVec &vec)
127{
128 PiecewiseVec new_vec;
129 set_boolean conditions;
130 for (auto &p : vec) {
131 if (eq(*p.second, *boolFalse)) {
132 continue;
133 } else if (eq(*p.second, *boolTrue)) {
134 new_vec.push_back(p);
135 conditions.insert(p.second);
136 break;
137 } else if (conditions.find(p.second) == conditions.end()) {
138 new_vec.push_back(p);
139 conditions.insert(p.second);
140 }
141 }
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;
146 }
147 return make_rcp<Piecewise>(std::move(new_vec));
148}
149
151{
152 SYMENGINE_ASSIGN_TYPEID()
153 SYMENGINE_ASSERT(is_canonical(vec_));
154}
155
156bool Piecewise::is_canonical(const PiecewiseVec &vec)
157{
158 set_boolean conditions;
159 bool found_true = false;
160 for (auto &p : vec) {
161 if (found_true) {
162 return false;
163 }
164 if (eq(*p.second, *boolFalse)) {
165 return false;
166 } else if (eq(*p.second, *boolTrue)) {
167 found_true = true;
168 } else if (conditions.find(p.second) == conditions.end()) {
169 conditions.insert(p.second);
170 } else {
171 return false;
172 }
173 }
174 if (vec.size() == 0) {
175 return false;
176 } else if (vec.size() == 1 and eq(*vec[0].second, *boolTrue)) {
177 return false;
178 }
179 return true;
180}
181
183{
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);
188 }
189 return seed;
190}
191
192const PiecewiseVec &Piecewise::get_vec() const
193{
194 return vec_;
195}
196
198{
199 vec_basic v;
200 for (auto &p : vec_) {
201 v.push_back(p.first);
202 v.push_back(p.second);
203 }
204 return v;
205}
206
207bool Piecewise::__eq__(const Basic &o) const
208{
209 return is_a<Piecewise>(o)
210 and unified_eq(get_vec(), down_cast<const Piecewise &>(o).get_vec());
211}
212
213int Piecewise::compare(const Basic &o) const
214{
215 SYMENGINE_ASSERT(is_same_type(*this, o))
216 RCP<const Piecewise> t = o.rcp_from_this_cast<Piecewise>();
217 return unified_compare(get_vec(), t->get_vec());
218}
219
220And::And(const set_boolean &s) : container_{s}
221{
222 SYMENGINE_ASSIGN_TYPEID()
223 SYMENGINE_ASSERT(is_canonical(s));
224}
225
226hash_t And::__hash__() const
227{
228 hash_t seed = SYMENGINE_AND;
229 for (const auto &a : container_)
230 hash_combine<Basic>(seed, *a);
231 return seed;
232}
233
235{
236 vec_basic v(container_.begin(), container_.end());
237 return v;
238}
239
240bool And::__eq__(const Basic &o) const
241{
242 return is_a<And>(o)
243 and unified_eq(container_,
244 down_cast<const And &>(o).get_container());
245}
246
247int And::compare(const Basic &o) const
248{
249 SYMENGINE_ASSERT(is_a<And>(o))
250 return unified_compare(container_,
251 down_cast<const And &>(o).get_container());
252}
253
254bool And::is_canonical(const set_boolean &container_)
255{
256 if (container_.size() >= 2) {
257 for (auto &a : container_) {
258 if (is_a<BooleanAtom>(*a) or is_a<And>(*a))
259 return false;
260 if (container_.find(SymEngine::logical_not(a)) != container_.end())
261 return false;
262 }
263 return true;
264 }
265 return false;
266}
267
268const set_boolean &And::get_container() const
269{
270 return container_;
271}
272
273RCP<const Basic> And::create(const set_boolean &a) const
274{
275 return logical_and(a);
276}
277
278RCP<const Boolean> And::logical_not() const
279{
280 auto container = this->get_container();
281 set_boolean cont;
282 for (auto &a : container) {
283 cont.insert(SymEngine::logical_not(a));
284 }
285 return make_rcp<const Or>(cont);
286}
287
288Or::Or(const set_boolean &s) : container_{s}
289{
290 SYMENGINE_ASSIGN_TYPEID()
291 SYMENGINE_ASSERT(is_canonical(s));
292}
293
294hash_t Or::__hash__() const
295{
296 hash_t seed = SYMENGINE_OR;
297 for (const auto &a : container_)
298 hash_combine<Basic>(seed, *a);
299 return seed;
300}
301
303{
304 vec_basic v(container_.begin(), container_.end());
305 return v;
306}
307
308bool Or::__eq__(const Basic &o) const
309{
310 return is_a<Or>(o)
311 and unified_eq(container_, down_cast<const Or &>(o).get_container());
312}
313
314int Or::compare(const Basic &o) const
315{
316 SYMENGINE_ASSERT(is_a<Or>(o))
317 return unified_compare(container_,
318 down_cast<const Or &>(o).get_container());
319}
320
321bool Or::is_canonical(const set_boolean &container_)
322{
323 if (container_.size() >= 2) {
324 for (auto &a : container_) {
325 if (is_a<BooleanAtom>(*a) or is_a<Or>(*a))
326 return false;
327 if (container_.find(SymEngine::logical_not(a)) != container_.end())
328 return false;
329 }
330 return true;
331 }
332 return false;
333}
334
335const set_boolean &Or::get_container() const
336{
337 return container_;
338}
339
340RCP<const Boolean> Or::logical_not() const
341{
342 auto container = this->get_container();
343 set_boolean cont;
344 for (auto &a : container) {
345 cont.insert(SymEngine::logical_not(a));
346 }
347 return make_rcp<const And>(cont);
348}
349
350Not::Not(const RCP<const Boolean> &in) : arg_{in}
351{
352 SYMENGINE_ASSIGN_TYPEID()
353 SYMENGINE_ASSERT(is_canonical(in));
354}
355
356hash_t Not::__hash__() const
357{
358 hash_t seed = SYMENGINE_NOT;
359 hash_combine<Basic>(seed, *arg_);
360 return seed;
361}
362
364{
365 vec_basic v;
366 v.push_back(arg_);
367 return v;
368}
369
370bool Not::__eq__(const Basic &o) const
371{
372 return is_a<Not>(o) and eq(*arg_, *down_cast<const Not &>(o).get_arg());
373}
374
375int Not::compare(const Basic &o) const
376{
377 SYMENGINE_ASSERT(is_a<Not>(o))
378 return arg_->__cmp__(*down_cast<const Not &>(o).get_arg());
379}
380
381bool Not::is_canonical(const RCP<const Boolean> &in)
382{
383 if (is_a<BooleanAtom>(*in) or is_a<Not>(*in))
384 return false;
385 return true;
386}
387
388RCP<const Boolean> Not::get_arg() const
389{
390 return arg_;
391}
392
393RCP<const Boolean> Not::logical_not() const
394{
395 return this->get_arg();
396}
397
398Xor::Xor(const vec_boolean &s) : container_{s}
399{
400 SYMENGINE_ASSIGN_TYPEID()
401 SYMENGINE_ASSERT(is_canonical(s));
402}
403
404hash_t Xor::__hash__() const
405{
406 hash_t seed = SYMENGINE_XOR;
407 for (const auto &a : container_)
408 hash_combine<Basic>(seed, *a);
409 return seed;
410}
411
413{
414 vec_basic v(container_.begin(), container_.end());
415 return v;
416}
417
418bool Xor::__eq__(const Basic &o) const
419{
420 return is_a<Xor>(o)
421 and unified_eq(container_,
422 down_cast<const Xor &>(o).get_container());
423}
424
425int Xor::compare(const Basic &o) const
426{
427 SYMENGINE_ASSERT(is_a<Xor>(o))
428 return unified_compare(container_,
429 down_cast<const Xor &>(o).get_container());
430}
431
432bool Xor::is_canonical(const vec_boolean &container_)
433{
434 if (container_.size() >= 2) {
435 set_boolean args;
436 for (auto &a : container_) {
437 if (is_a<BooleanAtom>(*a) or is_a<Xor>(*a)) {
438 return false;
439 }
440 if (args.find(a) != args.end()) {
441 return false;
442 }
443 if (args.find(SymEngine::logical_not(a)) != args.end()) {
444 return false;
445 }
446 args.insert(a);
447 }
448 return true;
449 }
450 return false;
451}
452
453const vec_boolean &Xor::get_container() const
454{
455 return container_;
456}
457
458const vec_boolean get_vec_from_set(const set_boolean &s)
459{
460 vec_boolean v(s.begin(), s.end());
461 return v;
462}
463
464template <typename caller>
465RCP<const Boolean> and_or(const set_boolean &s, const bool &op_x_notx)
466{
467 set_boolean args;
468 for (auto &a : s) {
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);
473 else
474 continue;
475 }
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());
480 continue;
481 }
482 args.insert(a);
483 }
484 for (auto &a : args) {
485 if (args.find(logical_not(a)) != args.end())
486 return boolean(op_x_notx);
487 }
488 if (not 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())
492 and is_a<FiniteSet>(
493 *down_cast<const Contains &>(**it).get_set())) {
494 auto sym = down_cast<const Contains &>(**it).get_expr();
495 // iterate through args and check for the condition that
496 // defines the domain of sym.
497 // Simplify if that set is a FiniteSet.
498 set_basic present;
499 auto fset = down_cast<const FiniteSet &>(
500 *down_cast<const Contains &>(**it).get_set())
501 .get_container();
502 // If there exists atleast one number/constant, then only we can
503 // simplify.
504 bool check = false;
505 for (const auto &elem : fset) {
506 if (is_a_Number(*elem) or is_a<Constant>(*elem)) {
507 check = true;
508 break;
509 }
510 }
511 if (!check)
512 break;
513 auto restCont = args;
514 restCont.erase(*it);
515 auto restCond = logical_and(restCont);
516 map_basic_basic d;
517 bool symexists = false;
518 for (const auto &fselement : fset) {
519 d[sym] = fselement;
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);
525 symexists = true;
526 }
527 d.clear();
528 }
529 if (not symexists) {
530 // if there are no symbols, then this reduces to a
531 // Contains(sym,finiteset())
532 return finiteset(present)->contains(sym);
533 } else if (present.size() != fset.size()) {
534 restCond = logical_and(
535 {finiteset(present)->contains(sym), restCond});
536 return restCond;
537 } else {
538 // if present is same as fset, then return object of type
539 // `And`.
540 break;
541 }
542 }
543 }
544 }
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);
550}
551
552RCP<const Boolean> logical_not(const RCP<const Boolean> &s)
553{
554 return s->logical_not();
555}
556
557RCP<const Boolean> logical_xor(const vec_boolean &s)
558{
559 set_boolean args;
560 int nots = 0;
561 for (auto &a : s) {
562 if (is_a<BooleanAtom>(*a)) {
563 auto val = down_cast<const BooleanAtom &>(*a).get_val();
564 if (val == true) {
565 nots++;
566 }
567 continue;
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()) {
572 args.erase(aa);
573 } else {
574 auto pos = args.find(logical_not(aa));
575 if (pos != args.end()) {
576 args.erase(pos);
577 nots++;
578 } else {
579 args.insert(aa);
580 }
581 }
582 }
583 continue;
584 }
585 if (args.find(a) != args.end()) {
586 args.erase(a);
587 } else {
588 auto pos = args.find(logical_not(a));
589 if (pos != args.end()) {
590 args.erase(pos);
591 nots++;
592 } else {
593 args.insert(a);
594 }
595 }
596 }
597
598 if (nots % 2 == 0) {
599 if (args.size() == 0) {
600 return boolFalse;
601 } else if (args.size() == 1) {
602 return *args.begin();
603 } else {
604 return make_rcp<const Xor>(get_vec_from_set(args));
605 }
606 } else {
607 if (args.size() == 0) {
608 return boolTrue;
609 } else if (args.size() == 1) {
610 return logical_not(*args.begin());
611 } else {
612 return make_rcp<const Not>(
613 make_rcp<const Xor>(get_vec_from_set(args)));
614 }
615 }
616}
617
618Relational::Relational(const RCP<const Basic> &lhs, const RCP<const Basic> &rhs)
619 : TwoArgBasic<Boolean>(lhs, rhs)
620{
621}
622
623inline bool Relational::is_canonical(const RCP<const Basic> &lhs,
624 const RCP<const Basic> &rhs) const
625{
626 if (eq(*lhs, *rhs))
627 return false;
628 if (is_a_Number(*lhs) and is_a_Number(*rhs))
629 return false;
630 if (is_a<BooleanAtom>(*lhs) and is_a<BooleanAtom>(*rhs))
631 return false;
632 return true;
633}
634
635Equality::Equality(const RCP<const Basic> &lhs, const RCP<const Basic> &rhs)
636 : Relational(lhs, rhs)
637{
638 SYMENGINE_ASSIGN_TYPEID();
639 SYMENGINE_ASSERT(is_canonical(lhs, rhs));
640}
641
642RCP<const Basic> Equality::create(const RCP<const Basic> &lhs,
643 const RCP<const Basic> &rhs) const
644{
645 return Eq(lhs, rhs);
646}
647
648RCP<const Boolean> Equality::logical_not() const
649{
650 return make_rcp<const Unequality>(get_arg1(), get_arg2());
651}
652
653RCP<const Boolean> Eq(const RCP<const Basic> &lhs)
654{
655 return Eq(lhs, zero);
656}
657
658RCP<const Boolean> Eq(const RCP<const Basic> &lhs, const RCP<const Basic> &rhs)
659{
660 if (is_a<NaN>(*lhs) or is_a<NaN>(*rhs))
661 return boolean(false);
662 bool b = eq(*lhs, *rhs);
663 if (b) {
664 return boolean(true);
665 } else {
666 if ((is_a_Number(*lhs) and is_a_Number(*rhs))
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);
672 }
673}
674
675Unequality::Unequality(const RCP<const Basic> &lhs, const RCP<const Basic> &rhs)
676 : Relational(lhs, rhs)
677{
678 SYMENGINE_ASSIGN_TYPEID();
679 SYMENGINE_ASSERT(is_canonical(lhs, rhs));
680}
681
682RCP<const Basic> Unequality::create(const RCP<const Basic> &lhs,
683 const RCP<const Basic> &rhs) const
684{
685 return Ne(lhs, rhs);
686}
687
688RCP<const Boolean> Unequality::logical_not() const
689{
690 return make_rcp<const Equality>(get_arg1(), get_arg2());
691}
692
693RCP<const Boolean> Ne(const RCP<const Basic> &lhs, const RCP<const Basic> &rhs)
694{
695 RCP<const Basic> r = Eq(lhs, rhs);
696 if (is_a<BooleanAtom>(*r)) {
697 return logical_not(rcp_static_cast<const BooleanAtom>(r));
698 }
699 if (lhs->__cmp__(*rhs) == 1)
700 return make_rcp<const Unequality>(rhs, lhs);
701 return make_rcp<Unequality>(lhs, rhs);
702}
703
704LessThan::LessThan(const RCP<const Basic> &lhs, const RCP<const Basic> &rhs)
705 : Relational(lhs, rhs)
706{
707 SYMENGINE_ASSIGN_TYPEID();
708 SYMENGINE_ASSERT(is_canonical(lhs, rhs));
709}
710
711RCP<const Basic> LessThan::create(const RCP<const Basic> &lhs,
712 const RCP<const Basic> &rhs) const
713{
714 return Le(lhs, rhs);
715}
716
717RCP<const Boolean> LessThan::logical_not() const
718{
719 return make_rcp<const StrictLessThan>(get_arg2(), get_arg1());
720}
721
722RCP<const Boolean> Le(const RCP<const Basic> &lhs, const RCP<const Basic> &rhs)
723{
724 if (is_a_Complex(*lhs) or is_a_Complex(*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.");
732 if (eq(*lhs, *rhs))
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);
740 }
741 return make_rcp<const LessThan>(lhs, rhs);
742}
743
744RCP<const Boolean> Ge(const RCP<const Basic> &lhs, const RCP<const Basic> &rhs)
745{
746 return Le(rhs, lhs);
747}
748
749StrictLessThan::StrictLessThan(const RCP<const Basic> &lhs,
750 const RCP<const Basic> &rhs)
751 : Relational(lhs, rhs)
752{
753 SYMENGINE_ASSIGN_TYPEID();
754 SYMENGINE_ASSERT(is_canonical(lhs, rhs));
755}
756
757RCP<const Basic> StrictLessThan::create(const RCP<const Basic> &lhs,
758 const RCP<const Basic> &rhs) const
759{
760 return Lt(lhs, rhs);
761}
762
763RCP<const Boolean> StrictLessThan::logical_not() const
764{
765 return make_rcp<const LessThan>(get_arg2(), get_arg1());
766}
767
768RCP<const Boolean> Lt(const RCP<const Basic> &lhs, const RCP<const Basic> &rhs)
769{
770 if (is_a_Complex(*lhs) or is_a_Complex(*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.");
778 if (eq(*lhs, *rhs))
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);
786 }
787 return make_rcp<const StrictLessThan>(lhs, rhs);
788}
789
790RCP<const Boolean> Gt(const RCP<const Basic> &lhs, const RCP<const Basic> &rhs)
791{
792 return Lt(rhs, lhs);
793}
794
795RCP<const Boolean> logical_and(const set_boolean &s)
796{
797 return and_or<And>(s, false);
798}
799
800RCP<const Boolean> logical_nand(const set_boolean &s)
801{
802 RCP<const Boolean> a = logical_and(s);
803 return logical_not(a);
804}
805
806RCP<const Boolean> logical_or(const set_boolean &s)
807{
808 return and_or<Or>(s, true);
809}
810
811RCP<const Boolean> logical_nor(const set_boolean &s)
812{
813 return logical_not(and_or<Or>(s, true));
814}
815
816RCP<const Boolean> logical_xnor(const vec_boolean &s)
817{
818 return logical_not(logical_xor(s));
819}
820} // namespace SymEngine
virtual vec_basic get_args() const
Returns the list of arguments.
Definition: logic.cpp:234
virtual int compare(const Basic &o) const
Structural equality comparator.
Definition: logic.cpp:247
virtual bool __eq__(const Basic &o) const
Test equality.
Definition: logic.cpp:240
hash_t __hash__() const
Definition: logic.cpp:226
The lowest unit of symbolic representation.
Definition: basic.h:97
virtual vec_basic get_args() const
Returns the list of arguments.
Definition: logic.cpp:85
virtual int compare(const Basic &o) const
Structural equality comparator.
Definition: logic.cpp:100
hash_t __hash__() const
Definition: logic.cpp:67
virtual bool __eq__(const Basic &o) const
Test equality.
Definition: logic.cpp:93
RCP< const T2 > rcp_from_this_cast() const
Get RCP<T2> pointer to self (it will cast the pointer to T2)
virtual RCP< const Basic > create(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs) const
Method to construct classes with canonicalization.
Definition: logic.cpp:642
virtual bool __eq__(const Basic &o) const
Test equality.
Definition: logic.cpp:370
hash_t __hash__() const
Definition: logic.cpp:356
virtual int compare(const Basic &o) const
Structural equality comparator.
Definition: logic.cpp:375
virtual vec_basic get_args() const
Returns the list of arguments.
Definition: logic.cpp:363
hash_t __hash__() const
Definition: logic.cpp:294
virtual bool __eq__(const Basic &o) const
Test equality.
Definition: logic.cpp:308
virtual vec_basic get_args() const
Returns the list of arguments.
Definition: logic.cpp:302
virtual int compare(const Basic &o) const
Structural equality comparator.
Definition: logic.cpp:314
Piecewise(PiecewiseVec &&vec)
Constructor.
Definition: logic.cpp:150
virtual int compare(const Basic &o) const
Structural equality comparator.
Definition: logic.cpp:213
hash_t __hash__() const
Definition: logic.cpp:182
virtual bool __eq__(const Basic &o) const
Test equality.
Definition: logic.cpp:207
virtual vec_basic get_args() const
Returns the list of arguments.
Definition: logic.cpp:197
Relational(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Constructor.
Definition: logic.cpp:618
virtual bool is_canonical(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs) const
Definition: logic.cpp:623
RCP< const Basic > get_arg2() const
Definition: functions.h:96
RCP< const Basic > get_arg1() const
Definition: functions.h:91
virtual int compare(const Basic &o) const
Definition: logic.cpp:425
virtual vec_basic get_args() const
Returns the list of arguments.
Definition: logic.cpp:412
virtual bool __eq__(const Basic &o) const
Test equality.
Definition: logic.cpp:418
T end(T... args)
T erase(T... args)
T find(T... args)
T insert(T... args)
T move(T... args)
Main namespace for SymEngine package.
Definition: add.cpp:19
bool is_a_Number(const Basic &b)
Definition: number.h:130
RCP< const Boolean > Ge(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Convenience function returning LessThan object.
Definition: logic.cpp:744
RCP< const Set > finiteset(const set_basic &container)
Definition: sets.h:574
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
Definition: basic-inl.h:21
RCP< const Boolean > Lt(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Returns the canonicalized StrictLessThan object from the arguments.
Definition: logic.cpp:768
RCP< const Boolean > Le(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Returns the canonicalized LessThan object from the arguments.
Definition: logic.cpp:722
bool is_same_type(const Basic &a, const Basic &b)
Returns true if a and b are exactly the same type T.
Definition: basic-inl.h:47
RCP< const Boolean > Eq(const RCP< const Basic > &lhs)
Returns the canonicalized Equality object from a single argument.
Definition: logic.cpp:653
int unified_compare(const T &a, const T &b)
Definition: dict.h:205
bool is_a_Complex(const Basic &b)
Definition: complex.h:24
RCP< const Boolean > Gt(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Convenience function returning StrictLessThan object.
Definition: logic.cpp:790
RCP< const Boolean > Ne(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Returns the canonicalized Unequality object from the arguments.
Definition: logic.cpp:693
T push_back(T... args)
T size(T... args)