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