sets.cpp
1 #include <symengine/add.h>
2 #include <symengine/logic.h>
3 #include <symengine/functions.h>
4 #include <symengine/symengine_casts.h>
5 #include <iterator>
6 
7 namespace SymEngine
8 {
9 
10 Interval::Interval(const RCP<const Number> &start, const RCP<const Number> &end,
11  const bool left_open, const bool right_open)
12  : start_(start), end_(end), left_open_(left_open), right_open_(right_open)
13 {
14  SYMENGINE_ASSIGN_TYPEID()
15  SYMENGINE_ASSERT(
16  Interval::is_canonical(start_, end_, left_open_, right_open_));
17 }
18 
19 bool Interval::is_canonical(const RCP<const Number> &s,
20  const RCP<const Number> &e, bool left_open,
21  bool right_open)
22 {
23  if (is_a<Complex>(*s) or is_a<Complex>(*e))
24  throw NotImplementedError("Complex set not implemented");
25  if (eq(*e, *s)) {
26  return false;
27  } else if (eq(*min({s, e}), *e)) {
28  return false;
29  }
30  return true;
31 }
32 
33 hash_t Interval::__hash__() const
34 {
35  hash_t seed = SYMENGINE_INTERVAL;
36  hash_combine<Basic>(seed, *start_);
37  hash_combine<Basic>(seed, *end_);
38  hash_combine<bool>(seed, left_open_);
39  hash_combine<bool>(seed, right_open_);
40  return seed;
41 }
42 
43 bool Interval::__eq__(const Basic &o) const
44 {
45  if (is_a<Interval>(o)) {
46  const Interval &s = down_cast<const Interval &>(o);
47  return ((this->left_open_ == s.left_open_)
48  and (this->right_open_ == s.right_open_)
49  and eq(*this->start_, *s.start_) and eq(*this->end_, *s.end_));
50  }
51  return false;
52 }
53 
54 int Interval::compare(const Basic &s) const
55 {
56  // compares two interval based on their length
57  SYMENGINE_ASSERT(is_a<Interval>(s))
58  const Interval &o = down_cast<const Interval &>(s);
59  if (left_open_ and not o.left_open_) {
60  return -1;
61  } else if (not left_open_ and o.left_open_) {
62  return 1;
63  } else if (right_open_ and not o.right_open_) {
64  return 1;
65  } else if (not right_open_ and o.right_open_) {
66  return -1;
67  } else {
68  auto temp = start_->__cmp__(*(o.start_));
69  if (temp != 0) {
70  return temp;
71  } else {
72  return end_->__cmp__(*(o.end_));
73  }
74  }
75 }
76 
77 RCP<const Set> Interval::open() const
78 {
79  return interval(start_, end_, true, true);
80 }
81 
82 RCP<const Set> Interval::Lopen() const
83 {
84  return interval(start_, end_, true, false);
85 }
86 
87 RCP<const Set> Interval::Ropen() const
88 {
89  return interval(start_, end_, false, true);
90 }
91 
92 RCP<const Set> Interval::close() const
93 {
94  return interval(start_, end_, false, false);
95 }
96 
97 RCP<const Boolean> Interval::contains(const RCP<const Basic> &a) const
98 {
99  if (not is_a_Number(*a)) {
100  if (is_a_Set(*a)) {
101  return boolean(false);
102  } else {
103  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
104  }
105  }
106  if (eq(*start_, *a))
107  return boolean(not left_open_);
108  if (eq(*end_, *a))
109  return boolean(not right_open_);
110  if (eq(*min({end_, a}), *end_) or eq(*max({start_, a}), *start_))
111  return boolean(false);
112  return boolean(true);
113 }
114 
115 RCP<const Set> Interval::set_intersection(const RCP<const Set> &o) const
116 {
117  if (is_a<Interval>(*o)) {
118  const Interval &other = down_cast<const Interval &>(*o);
119  RCP<const Number> start, end;
120  bool left_open, right_open;
121  RCP<const Basic> start_end, end_start;
122  start_end = min({this->start_, other.end_});
123  end_start = min({this->end_, other.start_});
124 
125  if (eq(*this->start_, *start_end) and eq(*other.start_, *end_start)) {
126  RCP<const Basic> start_start, end_end;
127  start_start = min({this->start_, other.start_});
128  end_end = min({this->end_, other.end_});
129  if (neq(*this->start_, *other.start_)) {
130  if (eq(*this->start_, *start_start)) {
131  start = other.start_;
132  left_open = other.left_open_;
133  } else {
134  start = this->start_;
135  left_open = this->left_open_;
136  }
137  } else {
138  start = this->start_;
139  left_open = this->left_open_ or other.left_open_;
140  }
141 
142  if (neq(*this->end_, *other.end_)) {
143  if (eq(*this->end_, *end_end)) {
144  end = this->end_;
145  right_open = this->right_open_;
146  } else {
147  end = other.end_;
148  right_open = other.right_open_;
149  }
150  } else {
151  end = this->end_;
152  right_open = this->right_open_ or other.right_open_;
153  }
154  return interval(start, end, left_open, right_open);
155  } else {
156  return emptyset();
157  }
158  }
159  if (is_a<Integers>(*o)) {
160  if (is_a_Number(*start_) and is_a_Number(*end_)) {
161  auto first = SymEngine::ceiling(start_);
162  auto last = SymEngine::floor(end_);
163  if (eq(*first, *start_) and left_open_) {
164  first = add(first, integer(1));
165  }
166  if (eq(*last, *end_) and right_open_) {
167  last = add(last, integer(-1));
168  }
169  if (eq(*Lt(last, first), *boolTrue)) {
170  return emptyset();
171  }
172  set_basic container;
173  while (eq(*Ge(last, first), *boolTrue)) {
174  container.insert(first);
175  first = add(first, integer(1));
176  }
177  return finiteset(container);
178  } else {
179  return SymEngine::set_intersection(
180  {rcp_from_this_cast<const Set>(), o});
181  }
182  }
183  if (is_a<UniversalSet>(*o) or is_a<EmptySet>(*o) or is_a<FiniteSet>(*o)
184  or is_a<Union>(*o) or is_a<Rationals>(*o) or is_a<Reals>(*o)) {
185  return (*o).set_intersection(rcp_from_this_cast<const Set>());
186  }
187  throw SymEngineException("Not implemented Intersection class");
188 }
189 
190 RCP<const Set> make_set_union(const set_set &in)
191 {
192  if (in.size() > 1) {
193  return make_rcp<const Union>(in);
194  }
195  return *in.begin();
196 }
197 
198 RCP<const Set> Interval::set_union(const RCP<const Set> &o) const
199 {
200  if (is_a<Interval>(*o)) {
201  const Interval &other = down_cast<const Interval &>(*o);
202  RCP<const Basic> start_start, end_end, m;
203  RCP<const Number> start, end;
204  bool left_open, right_open;
205  start_start = max({this->start_, other.start_});
206  end_end = min({this->end_, other.end_});
207  m = min({start_start, end_end});
208  if ((eq(*end_end, *start_start) and eq(*end_end, *m)
209  and ((eq(*end_end, *this->end_) and this->right_open_)
210  or (eq(*end_end, *other.end_) and other.right_open_)))
211  or (eq(*end_end, *m) and not eq(*end_end, *start_start))) {
212  return SymEngine::make_set_union(
213  {rcp_from_this_cast<const Set>(), o});
214  } else {
215  if (eq(*min({this->start_, other.start_}), *this->start_)) {
216  start = this->start_;
217  } else {
218  start = other.start_;
219  }
220  if (eq(*max({this->end_, other.end_}), *this->end_)) {
221  end = this->end_;
222  } else {
223  end = other.end_;
224  }
225  left_open = ((neq(*this->start_, *start) or this->left_open_)
226  and (neq(*other.start_, *start) or other.left_open_));
227  right_open = ((neq(*this->end_, *end) or this->right_open_)
228  and (neq(*other.end_, *end) or other.right_open_));
229  return interval(start, end, left_open, right_open);
230  }
231  }
232  if (is_a<UniversalSet>(*o) or is_a<EmptySet>(*o) or is_a<FiniteSet>(*o)
233  or is_a<Union>(*o) or is_a<Reals>(*o) or is_a<Rationals>(*o)
234  or is_a<Integers>(*o)) {
235  return (*o).set_union(rcp_from_this_cast<const Set>());
236  }
237  return SymEngine::make_set_union({rcp_from_this_cast<const Set>(), o});
238 }
239 
240 RCP<const Set> Interval::set_complement(const RCP<const Set> &o) const
241 {
242  if (is_a<Interval>(*o)) {
243  set_set cont;
244  const Interval &other = down_cast<const Interval &>(*o);
245  if (eq(*max({start_, other.start_}), *start_)) {
246  cont.insert(interval(other.get_start(), start_,
247  other.get_left_open(), not left_open_));
248  }
249  if (eq(*min({end_, other.end_}), *end_)) {
250  cont.insert(interval(end_, other.get_end(), not right_open_,
251  other.get_right_open()));
252  }
253  return SymEngine::set_union(cont);
254  }
255  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
256 }
257 
258 vec_basic Interval::get_args() const
259 {
260  return {start_, end_, boolean(left_open_), boolean(right_open_)};
261 }
262 
263 RCP<const Set> Reals::set_intersection(const RCP<const Set> &o) const
264 {
265  if (is_a<Interval>(*o) or is_a<EmptySet>(*o) or is_a<Reals>(*o)
266  or is_a<Rationals>(*o) or is_a<Integers>(*o)) {
267  return o;
268  } else if (is_a<FiniteSet>(*o)) {
269  return (*o).set_intersection(rcp_from_this_cast<const Set>());
270  } else {
271  return SymEngine::set_intersection(
272  {rcp_from_this_cast<const Set>(), o});
273  }
274 }
275 
276 RCP<const Set> Reals::set_union(const RCP<const Set> &o) const
277 {
278  if (is_a<Interval>(*o) or is_a<EmptySet>(*o) or is_a<Reals>(*o)
279  or is_a<Integers>(*o) or is_a<Rationals>(*o)) {
280  return reals();
281  } else if (is_a<FiniteSet>(*o)) {
282  return (*o).set_union(rcp_from_this_cast<const Set>());
283  } else {
284  return SymEngine::set_union({rcp_from_this_cast<const Set>(), o});
285  }
286 }
287 
288 RCP<const Set> Reals::set_complement(const RCP<const Set> &o) const
289 {
290  if (is_a<EmptySet>(*o) or is_a<Reals>(*o) or is_a<Rationals>(*o)
291  or is_a<Integers>(*o) or is_a<Interval>(*o)) {
292  return emptyset();
293  }
294  if (is_a<UniversalSet>(*o)) {
295  return make_rcp<const Complement>(o, reals());
296  }
297  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
298 }
299 
300 RCP<const Boolean> Reals::contains(const RCP<const Basic> &a) const
301 {
302  if (not is_a_Number(*a)) {
303  if (is_a_Set(*a)) {
304  return boolean(false);
305  } else {
306  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
307  }
308  }
309  if (is_a<Complex>(*a)) {
310  return boolean(false);
311  }
312  return boolean(true);
313 }
314 
315 hash_t Reals::__hash__() const
316 {
317  hash_t seed = SYMENGINE_REALS;
318  return seed;
319 }
320 
321 bool Reals::__eq__(const Basic &o) const
322 {
323  if (is_a<Reals>(o))
324  return true;
325  return false;
326 }
327 
328 int Reals::compare(const Basic &o) const
329 {
330  SYMENGINE_ASSERT(is_a<Reals>(o))
331  return 0;
332 }
333 
334 const RCP<const Reals> &Reals::getInstance()
335 {
336  const static auto a = make_rcp<const Reals>();
337  return a;
338 }
339 
340 RCP<const Set> Rationals::set_intersection(const RCP<const Set> &o) const
341 {
342  if (is_a<EmptySet>(*o) or is_a<Rationals>(*o) or is_a<Integers>(*o)) {
343  return o;
344  } else if (is_a<FiniteSet>(*o) or is_a<Reals>(*o)) {
345  return (*o).set_intersection(rcp_from_this_cast<const Set>());
346  } else {
347  return SymEngine::set_intersection(
348  {rcp_from_this_cast<const Set>(), o});
349  }
350 }
351 
352 RCP<const Set> Rationals::set_union(const RCP<const Set> &o) const
353 {
354  if (is_a<EmptySet>(*o) or is_a<Integers>(*o) or is_a<Rationals>(*o)) {
355  return rationals();
356  } else if (is_a<FiniteSet>(*o) or is_a<Reals>(*o)) {
357  return (*o).set_union(rcp_from_this_cast<const Set>());
358  } else {
359  return SymEngine::set_union({rcp_from_this_cast<const Set>(), o});
360  }
361 }
362 
363 RCP<const Set> Rationals::set_complement(const RCP<const Set> &o) const
364 {
365  if (is_a<EmptySet>(*o) or is_a<Rationals>(*o) or is_a<Integers>(*o)) {
366  return emptyset();
367  }
368  if (is_a<UniversalSet>(*o) or is_a<Reals>(*o) or is_a<Interval>(*o)) {
369  return make_rcp<const Complement>(o, rationals());
370  }
371  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
372 }
373 
374 RCP<const Boolean> Rationals::contains(const RCP<const Basic> &a) const
375 {
376  if (not is_a_Number(*a)) {
377  if (is_a_Set(*a)) {
378  return boolean(false);
379  } else {
380  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
381  }
382  }
383  if (is_a<Complex>(*a) or not down_cast<const Number &>(*a).is_exact()) {
384  return boolean(false);
385  }
386  return boolean(true);
387 }
388 
389 hash_t Rationals::__hash__() const
390 {
391  hash_t seed = SYMENGINE_RATIONALS;
392  return seed;
393 }
394 
395 bool Rationals::__eq__(const Basic &o) const
396 {
397  return (is_a<Rationals>(o));
398 }
399 
400 int Rationals::compare(const Basic &o) const
401 {
402  SYMENGINE_ASSERT(is_a<Rationals>(o))
403  return 0;
404 }
405 
406 const RCP<const Rationals> &Rationals::getInstance()
407 {
408  const static auto a = make_rcp<const Rationals>();
409  return a;
410 }
411 
412 RCP<const Set> Integers::set_intersection(const RCP<const Set> &o) const
413 {
414  if (is_a<EmptySet>(*o) or is_a<Integers>(*o)) {
415  return o;
416  } else if (is_a<Reals>(*o) or is_a<Rationals>(*o)) {
417  return integers();
418  } else if (is_a<FiniteSet>(*o) or is_a<Interval>(*o)) {
419  return (*o).set_intersection(rcp_from_this_cast<const Set>());
420  } else {
421  return SymEngine::set_intersection(
422  {rcp_from_this_cast<const Set>(), o});
423  }
424 }
425 
426 RCP<const Set> Integers::set_union(const RCP<const Set> &o) const
427 {
428  if (is_a<Integers>(*o) or is_a<EmptySet>(*o)) {
429  return integers();
430  } else if (is_a<Reals>(*o)) {
431  return reals();
432  } else if (is_a<Rationals>(*o)) {
433  return rationals();
434  } else if (is_a<FiniteSet>(*o)) {
435  return (*o).set_union(rcp_from_this_cast<const Set>());
436  } else if (is_a<UniversalSet>(*o)) {
437  return universalset();
438  } else {
439  return SymEngine::make_set_union({rcp_from_this_cast<const Set>(), o});
440  }
441 }
442 
443 RCP<const Set> Integers::set_complement(const RCP<const Set> &o) const
444 {
445  if (is_a<EmptySet>(*o) or is_a<Integers>(*o)) {
446  return emptyset();
447  }
448  if (is_a<UniversalSet>(*o) or is_a<Rationals>(*o) or is_a<Reals>(*o)) {
449  return make_rcp<const Complement>(o, integers());
450  }
451  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
452 }
453 
454 RCP<const Boolean> Integers::contains(const RCP<const Basic> &a) const
455 {
456  if (not is_a_Number(*a)) {
457  if (is_a_Set(*a)) {
458  return boolean(false);
459  } else {
460  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
461  }
462  }
463  if (is_a<Integer>(*a)) {
464  return boolean(true);
465  }
466  return boolean(false);
467 }
468 
469 hash_t Integers::__hash__() const
470 {
471  hash_t seed = SYMENGINE_INTEGERS;
472  return seed;
473 }
474 
475 bool Integers::__eq__(const Basic &o) const
476 {
477  if (is_a<Integers>(o))
478  return true;
479  return false;
480 }
481 
482 int Integers::compare(const Basic &o) const
483 {
484  SYMENGINE_ASSERT(is_a<Integers>(o))
485  return 0;
486 }
487 
488 const RCP<const Integers> &Integers::getInstance()
489 {
490  const static auto a = make_rcp<const Integers>();
491  return a;
492 }
493 
494 RCP<const Set> EmptySet::set_intersection(const RCP<const Set> &o) const
495 {
496  return emptyset();
497 }
498 
499 RCP<const Set> EmptySet::set_union(const RCP<const Set> &o) const
500 {
501  return o;
502 }
503 
504 RCP<const Set> EmptySet::set_complement(const RCP<const Set> &o) const
505 {
506  return o;
507 }
508 
509 hash_t EmptySet::__hash__() const
510 {
511  hash_t seed = SYMENGINE_EMPTYSET;
512  return seed;
513 }
514 
515 bool EmptySet::__eq__(const Basic &o) const
516 {
517  if (is_a<EmptySet>(o))
518  return true;
519  return false;
520 }
521 
522 int EmptySet::compare(const Basic &o) const
523 {
524  SYMENGINE_ASSERT(is_a<EmptySet>(o))
525  return 0;
526 }
527 
528 const RCP<const EmptySet> &EmptySet::getInstance()
529 {
530  const static auto a = make_rcp<const EmptySet>();
531  return a;
532 }
533 
534 RCP<const Set> UniversalSet::set_intersection(const RCP<const Set> &o) const
535 {
536  return o;
537 }
538 
539 RCP<const Set> UniversalSet::set_union(const RCP<const Set> &o) const
540 {
541  return universalset();
542 }
543 
544 RCP<const Set> UniversalSet::set_complement(const RCP<const Set> &o) const
545 {
546  return emptyset();
547 }
548 
549 hash_t UniversalSet::__hash__() const
550 {
551  hash_t seed = SYMENGINE_UNIVERSALSET;
552  return seed;
553 }
554 
555 bool UniversalSet::__eq__(const Basic &o) const
556 {
557  if (is_a<UniversalSet>(o))
558  return true;
559  return false;
560 }
561 
562 int UniversalSet::compare(const Basic &o) const
563 {
564  SYMENGINE_ASSERT(is_a<UniversalSet>(o))
565  return 0;
566 }
567 
568 const RCP<const UniversalSet> &UniversalSet::getInstance()
569 {
570  const static auto a = make_rcp<const UniversalSet>();
571  return a;
572 }
573 
574 FiniteSet::FiniteSet(const set_basic &container) : container_(container)
575 {
576  SYMENGINE_ASSIGN_TYPEID()
577  SYMENGINE_ASSERT(FiniteSet::is_canonical(container_));
578 }
579 
580 bool FiniteSet::is_canonical(const set_basic &container)
581 {
582  return container.size() != 0;
583 }
584 
585 hash_t FiniteSet::__hash__() const
586 {
587  hash_t seed = SYMENGINE_FINITESET;
588  for (const auto &a : container_)
589  hash_combine<Basic>(seed, *a);
590  return seed;
591 }
592 
593 bool FiniteSet::__eq__(const Basic &o) const
594 {
595  if (is_a<FiniteSet>(o)) {
596  const FiniteSet &other = down_cast<const FiniteSet &>(o);
597  return unified_eq(container_, other.container_);
598  }
599  return false;
600 }
601 
602 int FiniteSet::compare(const Basic &o) const
603 {
604  // compares two FiniteSet based on their length
605  SYMENGINE_ASSERT(is_a<FiniteSet>(o))
606  const FiniteSet &other = down_cast<const FiniteSet &>(o);
607  return unified_compare(container_, other.container_);
608 }
609 
610 RCP<const Boolean> FiniteSet::contains(const RCP<const Basic> &a) const
611 {
612  set_basic rest;
613  for (const auto &elem : container_) {
614  auto cont = Eq(elem, a);
615  if (eq(*cont, *boolTrue))
616  return boolTrue;
617  if (not eq(*cont, *boolFalse))
618  rest.insert(elem);
619  }
620  if (rest.empty()) {
621  return boolFalse;
622  } else {
623  return make_rcp<Contains>(a, finiteset(rest));
624  }
625 }
626 
627 RCP<const Set> FiniteSet::set_union(const RCP<const Set> &o) const
628 {
629  if (is_a<FiniteSet>(*o)) {
630  const FiniteSet &other = down_cast<const FiniteSet &>(*o);
631  set_basic container;
632  std::set_union(container_.begin(), container_.end(),
633  other.container_.begin(), other.container_.end(),
634  std::inserter(container, container.begin()),
635  RCPBasicKeyLess{});
636  return finiteset(container);
637  }
638  if (is_a<Interval>(*o)) {
639  set_basic container;
640  const Interval &other = down_cast<const Interval &>(*o);
641  bool left = other.get_left_open(), right = other.get_right_open();
642  for (const auto &a : container_) {
643  auto contain = o->contains(a);
644  if (eq(*contain, *boolFalse)) {
645  if (left)
646  if (eq(*other.get_start(), *a)) {
647  left = false;
648  continue;
649  }
650  if (right)
651  if (eq(*other.get_end(), *a)) {
652  right = false;
653  continue;
654  }
655  container.insert(a);
656  } else if (is_a<Contains>(*contain)) {
657  container.insert(a);
658  }
659  }
660  if (not container.empty()) {
661  if (left == other.get_left_open()
662  and right == other.get_right_open()) {
663  return SymEngine::make_set_union({finiteset(container), o});
664  } else {
665  return SymEngine::make_set_union(
666  set_set({finiteset(container),
667  interval(other.get_start(), other.get_end(), left,
668  right)}));
669  }
670  } else {
671  if (left == other.get_left_open()
672  and right == other.get_right_open()) {
673  return o;
674  } else {
675  return interval(other.get_start(), other.get_end(), left,
676  right);
677  }
678  }
679  }
680  if (is_a<Reals>(*o)) {
681  set_basic container;
682  for (const auto &elem : container_) {
683  if (!is_a_Number(*elem)
684  || down_cast<const Number &>(*elem).is_complex()) {
685  container.insert(elem);
686  }
687  }
688  if (container.empty()) {
689  return reals();
690  } else {
691  return SymEngine::make_set_union({reals(), finiteset(container)});
692  }
693  }
694  if (is_a<Rationals>(*o)) {
695  set_basic container;
696  for (const auto &elem : container_) {
697  if (!is_a_Number(*elem)
698  || down_cast<const Number &>(*elem).is_complex()) {
699  container.insert(elem);
700  }
701  }
702  if (container.empty()) {
703  return rationals();
704  } else {
705  return SymEngine::make_set_union(
706  {rationals(), finiteset(container)});
707  }
708  }
709  if (is_a<Integers>(*o)) {
710  set_basic container;
711  for (const auto &elem : container_) {
712  if (!is_a<Integer>(*elem)) {
713  container.insert(elem);
714  }
715  }
716  if (container.empty()) {
717  return integers();
718  } else {
719  return SymEngine::make_set_union(
720  {integers(), finiteset(container)});
721  }
722  }
723  if (is_a<UniversalSet>(*o) or is_a<EmptySet>(*o) or is_a<Union>(*o)) {
724  return (*o).set_union(rcp_from_this_cast<const Set>());
725  }
726  return SymEngine::make_set_union({rcp_from_this_cast<const Set>(), o});
727 }
728 
729 RCP<const Set> FiniteSet::set_intersection(const RCP<const Set> &o) const
730 {
731  if (is_a<FiniteSet>(*o)) {
732  const FiniteSet &other = down_cast<const FiniteSet &>(*o);
733  set_basic container;
734  std::set_intersection(container_.begin(), container_.end(),
735  other.container_.begin(), other.container_.end(),
736  std::inserter(container, container.begin()),
737  RCPBasicKeyLess{});
738  return finiteset(container);
739  }
740  if (is_a<Interval>(*o)) {
741  set_basic container;
742  for (const auto &a : container_) {
743  auto contain = o->contains(a);
744  if (eq(*contain, *boolTrue))
745  container.insert(a);
746  if (is_a<Contains>(*contain))
747  throw SymEngineException("Not implemented");
748  }
749  return finiteset(container);
750  }
751  if (is_a<Reals>(*o) or is_a<Rationals>(*o)) {
752  set_basic kept;
753  set_basic others;
754  for (const auto &elem : container_) {
755  if (is_a_Number(*elem)) {
756  if (!down_cast<const Number &>(*elem).is_complex()) {
757  if (!is_a<Rationals>(*o)
758  or down_cast<const Number &>(*elem).is_exact()) {
759  kept.insert(elem);
760  }
761  }
762  } else {
763  others.insert(elem);
764  }
765  }
766  if (kept.empty()) {
767  if (others.empty()) {
768  return emptyset();
769  } else {
770  return SymEngine::set_intersection({o, finiteset(others)});
771  }
772  } else {
773  if (others.empty()) {
774  return finiteset(kept);
775  } else {
776  others.insert(kept.begin(), kept.end());
777  return SymEngine::set_intersection({o, finiteset(others)});
778  }
779  }
780  }
781  if (is_a<Integers>(*o)) {
782  set_basic kept_integers;
783  set_basic others;
784  for (const auto &elem : container_) {
785  if (is_a_Number(*elem)) {
786  if (is_a<Integer>(*elem)) {
787  kept_integers.insert(elem);
788  }
789  } else {
790  others.insert(elem);
791  }
792  }
793  if (kept_integers.empty()) {
794  if (others.empty()) {
795  return emptyset();
796  } else {
797  return SymEngine::set_intersection(
798  {integers(), finiteset(others)});
799  }
800  } else {
801  if (others.empty()) {
802  return finiteset(kept_integers);
803  } else {
804  others.insert(kept_integers.begin(), kept_integers.end());
805  return SymEngine::set_intersection(
806  {integers(), finiteset(others)});
807  }
808  }
809  }
810  if (is_a<UniversalSet>(*o) or is_a<EmptySet>(*o) or is_a<Union>(*o)) {
811  return (*o).set_intersection(rcp_from_this_cast<const Set>());
812  }
813  throw SymEngineException("Not implemented Intersection class");
814 }
815 
816 RCP<const Set> FiniteSet::set_complement(const RCP<const Set> &o) const
817 {
818  if (is_a<FiniteSet>(*o)) {
819  const FiniteSet &other = down_cast<const FiniteSet &>(*o);
820  set_basic container;
821  std::set_difference(other.container_.begin(), other.container_.end(),
822  container_.begin(), container_.end(),
823  std::inserter(container, container.begin()),
824  RCPBasicKeyLess{});
825  return finiteset(container);
826  }
827 
828  if (is_a<Interval>(*o)) {
829  set_set intervals;
830  auto &other = down_cast<const Interval &>(*o);
831  RCP<const Number> last = other.get_start();
832  RCP<const Number> a_num;
833  set_basic rest;
834  bool left_open = other.get_left_open(),
835  right_open = other.get_right_open();
836  for (auto it = container_.begin(); it != container_.end(); it++) {
837  if (eq(*max({*it, other.get_start()}), *other.get_start())) {
838  if (eq(**it, *other.get_start()))
839  left_open = true;
840  continue;
841  }
842  if (eq(*max({*it, other.get_end()}), **it)) {
843  if (eq(**it, *other.get_end()))
844  right_open = true;
845  break;
846  }
847  if (is_a_Number(**it)) {
848  a_num = rcp_static_cast<const Number>(*it);
849  intervals.insert(interval(last, a_num, left_open, true));
850  last = a_num;
851  left_open = true;
852  } else {
853  rest.insert(*it);
854  }
855  }
856 
857  if (eq(*max({last, other.get_end()}), *other.get_end())) {
858  intervals.insert(
859  interval(last, other.get_end(), left_open, right_open));
860  }
861  if (rest.empty()) {
862  return SymEngine::make_set_union(intervals);
863  } else {
864  return make_rcp<const Complement>(
865  SymEngine::make_set_union(intervals), finiteset(rest));
866  }
867  }
868 
869  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
870 }
871 
872 RCP<const Set> FiniteSet::create(const set_basic &container) const
873 {
874  return finiteset(container);
875 }
876 
877 Union::Union(const set_set &in)
878  : container_(in){SYMENGINE_ASSIGN_TYPEID()
879  SYMENGINE_ASSERT(Union::is_canonical(in))}
880 
881  hash_t Union::__hash__() const
882 {
883  hash_t seed = SYMENGINE_UNION;
884  for (const auto &a : container_)
885  hash_combine<Basic>(seed, *a);
886  return seed;
887 }
888 
889 bool Union::__eq__(const Basic &o) const
890 {
891  if (is_a<Union>(o)) {
892  const Union &other = down_cast<const Union &>(o);
893  return unified_eq(container_, other.container_);
894  }
895  return false;
896 }
897 
898 bool Union::is_canonical(const set_set &in)
899 {
900  if (in.size() <= 1)
901  return false;
902  int count = 0;
903  for (const auto &s : in) {
904  if (is_a<FiniteSet>(*s)) {
905  count++;
906  }
907  if (count >= 2)
908  return false;
909  }
910  return true;
911 }
912 
913 int Union::compare(const Basic &o) const
914 {
915  SYMENGINE_ASSERT(is_a<Union>(o))
916  const Union &other = down_cast<const Union &>(o);
917  return unified_compare(container_, other.container_);
918 }
919 
920 RCP<const Set> Union::set_union(const RCP<const Set> &o) const
921 {
922  set_set container(container_);
923  for (auto iter = container.begin(); iter != container.end(); ++iter) {
924  auto temp = o->set_union(*iter);
925  // If we are able to do union with `*iter`, we replace `*iter` with
926  // the result of union.
927  auto un = SymEngine::make_set_union({o, *iter});
928  if (not eq(*temp, *un)) {
929  iter = container.erase(iter);
930  container.insert(temp);
931  return SymEngine::set_union(container);
932  }
933  }
934  container.insert(o);
935  return SymEngine::make_set_union(container);
936 }
937 
938 RCP<const Set> Union::set_intersection(const RCP<const Set> &o) const
939 {
940  set_set container;
941  for (auto &a : container_) {
942  container.insert(a->set_intersection(o));
943  }
944  return SymEngine::set_union(container);
945 }
946 
947 RCP<const Set> Union::set_complement(const RCP<const Set> &o) const
948 {
949  set_set container;
950  for (auto &a : container_) {
951  container.insert(a->set_complement(o));
952  }
953  return SymEngine::set_intersection(container);
954 }
955 
956 RCP<const Boolean> Union::contains(const RCP<const Basic> &o) const
957 {
958  for (auto &a : container_) {
959  auto contain = a->contains(o);
960  if (eq(*contain, *boolTrue)) {
961  return boolean(true);
962  }
963  if (is_a<Contains>(*contain))
964  throw NotImplementedError("Not implemented");
965  }
966  return boolean(false);
967 }
968 
969 RCP<const Set> Union::create(const set_set &in) const
970 {
971  return SymEngine::set_union(in);
972 }
973 
975 {
976  vec_basic v(container_.begin(), container_.end());
977  return v;
978 }
979 
980 Complement::Complement(const RCP<const Set> &universe,
981  const RCP<const Set> &container)
982  : universe_(universe), container_(container){SYMENGINE_ASSIGN_TYPEID()}
983 
984  hash_t Complement::__hash__() const
985 {
986  hash_t seed = SYMENGINE_COMPLEMENT;
987  hash_combine<Basic>(seed, *universe_);
988  hash_combine<Basic>(seed, *container_);
989  return seed;
990 }
991 
992 bool Complement::__eq__(const Basic &o) const
993 {
994  if (is_a<Complement>(o)) {
995  const Complement &other = down_cast<const Complement &>(o);
996  return unified_eq(universe_, other.universe_)
997  and unified_eq(container_, other.container_);
998  }
999  return false;
1000 }
1001 
1002 int Complement::compare(const Basic &o) const
1003 {
1004  SYMENGINE_ASSERT(is_a<Complement>(o))
1005  const Complement &other = down_cast<const Complement &>(o);
1006  int c1 = unified_compare(universe_, other.universe_);
1007  if (c1 != 0) {
1008  return c1;
1009  } else {
1010  return unified_compare(container_, other.container_);
1011  }
1012 }
1013 
1014 RCP<const Boolean> Complement::contains(const RCP<const Basic> &a) const
1015 {
1016  return logical_and(
1017  {universe_->contains(a), logical_not(container_->contains(a))});
1018 }
1019 
1020 RCP<const Set> Complement::set_union(const RCP<const Set> &o) const
1021 {
1022  // A' U C = (A n C')'
1023  RCP<const Set> ocomplement = o->set_complement(universe_);
1024  RCP<const Set> intersect
1025  = SymEngine::set_intersection({container_, ocomplement});
1026  return intersect->set_complement(universe_);
1027 }
1028 
1029 RCP<const Set> Complement::set_intersection(const RCP<const Set> &o) const
1030 {
1031  return SymEngine::set_intersection({rcp_from_this_cast<const Set>(), o});
1032 }
1033 
1034 RCP<const Set> Complement::set_complement(const RCP<const Set> &o) const
1035 {
1036  auto newuniv = SymEngine::set_union({o, universe_});
1037  return container_->set_complement(newuniv);
1038 }
1039 
1040 ConditionSet::ConditionSet(const RCP<const Basic> &sym,
1041  const RCP<const Boolean> &condition)
1042  : sym(sym), condition_(condition)
1043 {
1044  SYMENGINE_ASSIGN_TYPEID()
1045  SYMENGINE_ASSERT(ConditionSet::is_canonical(sym, condition))
1046 }
1047 
1048 bool ConditionSet::is_canonical(const RCP<const Basic> &sym,
1049  const RCP<const Boolean> &condition)
1050 {
1051  if (eq(*condition, *boolFalse) or eq(*condition, *boolTrue)
1052  or not is_a_sub<Symbol>(*sym)) {
1053  return false;
1054  } else if (is_a<Contains>(*condition)) {
1055  return false;
1056  }
1057  return true;
1058 }
1059 
1061 {
1062  hash_t seed = SYMENGINE_CONDITIONSET;
1063  hash_combine<Basic>(seed, *sym);
1064  hash_combine<Basic>(seed, *condition_);
1065  return seed;
1066 }
1067 
1068 bool ConditionSet::__eq__(const Basic &o) const
1069 {
1070  if (is_a<ConditionSet>(o)) {
1071  const ConditionSet &other = down_cast<const ConditionSet &>(o);
1072  return unified_eq(sym, other.get_symbol())
1073  and unified_eq(condition_, other.get_condition());
1074  }
1075  return false;
1076 }
1077 
1078 int ConditionSet::compare(const Basic &o) const
1079 {
1080  SYMENGINE_ASSERT(is_a<ConditionSet>(o))
1081  const ConditionSet &other = down_cast<const ConditionSet &>(o);
1082  int c1 = unified_compare(sym, other.get_symbol());
1083  if (c1 != 0) {
1084  return c1;
1085  } else {
1086  return unified_compare(condition_, other.get_condition());
1087  }
1088 }
1089 
1090 RCP<const Set> ConditionSet::set_union(const RCP<const Set> &o) const
1091 {
1092  return SymEngine::make_set_union({o, rcp_from_this_cast<const Set>()});
1093 }
1094 
1095 RCP<const Set> ConditionSet::set_intersection(const RCP<const Set> &o) const
1096 {
1097  if (not is_a<ConditionSet>(*o)) {
1098  return conditionset(sym, logical_and({condition_, o->contains(sym)}));
1099  }
1100  throw SymEngineException("Not implemented Intersection class");
1101 }
1102 
1103 RCP<const Set> ConditionSet::set_complement(const RCP<const Set> &o) const
1104 {
1105  return make_rcp<const Complement>(o, rcp_from_this_cast<const Set>());
1106 }
1107 
1108 RCP<const Boolean> ConditionSet::contains(const RCP<const Basic> &o) const
1109 {
1110  map_basic_basic d;
1111  d[sym] = o;
1112  auto cond = condition_->subs(d);
1113  if (not is_a_Boolean(*cond)) {
1114  throw SymEngineException("expected an object of type Boolean");
1115  }
1116  return rcp_static_cast<const Boolean>(cond);
1117 }
1118 
1119 ImageSet::ImageSet(const RCP<const Basic> &sym, const RCP<const Basic> &expr,
1120  const RCP<const Set> &base)
1121  : sym_(sym), expr_(expr), base_(base)
1122 {
1123  SYMENGINE_ASSIGN_TYPEID()
1124  SYMENGINE_ASSERT(ImageSet::is_canonical(sym, expr, base));
1125 }
1126 
1127 hash_t ImageSet::__hash__() const
1128 {
1129  hash_t seed = SYMENGINE_IMAGESET;
1130  hash_combine<Basic>(seed, *sym_);
1131  hash_combine<Basic>(seed, *expr_);
1132  hash_combine<Basic>(seed, *base_);
1133  return seed;
1134 }
1135 
1136 bool ImageSet::__eq__(const Basic &o) const
1137 {
1138  if (is_a<ImageSet>(o)) {
1139  const ImageSet &other = down_cast<const ImageSet &>(o);
1140  return unified_eq(sym_, other.sym_) and unified_eq(expr_, other.expr_)
1141  and unified_eq(base_, other.base_);
1142  }
1143  return false;
1144 }
1145 
1146 int ImageSet::compare(const Basic &o) const
1147 {
1148  SYMENGINE_ASSERT(is_a<ImageSet>(o))
1149  const ImageSet &other = down_cast<const ImageSet &>(o);
1150  int c1 = unified_compare(sym_, other.sym_);
1151  if (c1 != 0) {
1152  return c1;
1153  } else {
1154  int c2 = unified_compare(expr_, other.expr_);
1155  if (c2 != 0) {
1156  return c2;
1157  } else {
1158  return unified_compare(base_, other.base_);
1159  }
1160  }
1161 }
1162 
1163 bool ImageSet::is_canonical(const RCP<const Basic> &sym,
1164  const RCP<const Basic> &expr,
1165  const RCP<const Set> &base)
1166 {
1167  if (not is_a_sub<Symbol>(*sym) or eq(*expr, *sym) or is_a_Number(*expr)
1168  or eq(*base, *emptyset()))
1169  return false;
1170  return true;
1171 }
1172 
1173 RCP<const Boolean> ImageSet::contains(const RCP<const Basic> &a) const
1174 {
1175  throw SymEngineException("Not implemented");
1176 }
1177 
1178 RCP<const Set> ImageSet::set_union(const RCP<const Set> &o) const
1179 {
1180  return make_set_union({rcp_from_this_cast<const Set>(), o});
1181 }
1182 
1183 RCP<const Set> ImageSet::set_intersection(const RCP<const Set> &o) const
1184 {
1185  return SymEngine::set_intersection({rcp_from_this_cast<const Set>(), o});
1186 }
1187 
1188 RCP<const Set> ImageSet::set_complement(const RCP<const Set> &o) const
1189 {
1190  return SymEngine::set_complement(rcp_from_this_cast<const Set>(), o);
1191 }
1192 
1193 RCP<const Set> ImageSet::create(const RCP<const Basic> &sym,
1194  const RCP<const Basic> &expr,
1195  const RCP<const Set> &base) const
1196 {
1197  return imageset(sym, expr, base);
1198 }
1199 
1200 RCP<const Set> set_union(const set_set &in)
1201 {
1202  set_set input;
1203  set_basic combined_FiniteSet;
1204  for (auto it = in.begin(); it != in.end(); ++it) {
1205  if (is_a<FiniteSet>(**it)) {
1206  const FiniteSet &other = down_cast<const FiniteSet &>(**it);
1207  combined_FiniteSet.insert(other.get_container().begin(),
1208  other.get_container().end());
1209  } else if (is_a<UniversalSet>(**it)) {
1210  return universalset();
1211  } else if (not is_a<EmptySet>(**it)) {
1212  input.insert(*it);
1213  }
1214  }
1215  if (input.empty()) {
1216  return finiteset(combined_FiniteSet);
1217  } else if (input.size() == 1 && combined_FiniteSet.empty()) {
1218  return *input.begin();
1219  }
1220  // Now we rely on respective containers' own rules
1221  // TODO: Improve it to O(log n)
1222  RCP<const Set> combined_Rest = finiteset(combined_FiniteSet);
1223  for (auto it = input.begin(); it != input.end(); ++it) {
1224  combined_Rest = combined_Rest->set_union(*it);
1225  }
1226  return combined_Rest;
1227 }
1228 
1229 RCP<const Set> set_intersection(const set_set &in)
1230 {
1231  // https://en.wikipedia.org/wiki/Intersection_(set_theory)#Nullary_intersection
1232  if (in.empty())
1233  return universalset();
1234 
1235  // Global rules
1236  // If found any emptyset then return emptyset
1237  set_set incopy;
1238  for (const auto &input : in) {
1239  if (is_a<EmptySet>(*input)) {
1240  return emptyset();
1241  } else if (not is_a<UniversalSet>(*input)) {
1242  incopy.insert(input);
1243  }
1244  }
1245 
1246  if (incopy.empty())
1247  return universalset();
1248  if (incopy.size() == 1)
1249  return *incopy.begin();
1250 
1251  // Handle finite sets
1252  std::vector<RCP<const Set>> fsets, othersets;
1253  for (const auto &input : incopy) {
1254  if (is_a<FiniteSet>(*input)) {
1255  fsets.push_back(input);
1256  } else {
1257  othersets.push_back(input);
1258  }
1259  }
1260  if (fsets.size() != 0) {
1261  const FiniteSet &fs = down_cast<const FiniteSet &>(**fsets.begin());
1262  auto cont = fs.get_container();
1263  fsets.erase(fsets.begin());
1264  set_basic finalfs;
1265  for (const auto &fselement : cont) {
1266  bool present = true;
1267  for (const auto &fset : fsets) {
1268  auto contain = fset->contains(fselement);
1269  if (not(eq(*contain, *boolTrue) or eq(*contain, *boolFalse))) {
1270  throw SymEngineException(
1271  "Not implemented Intersection class");
1272  }
1273  present = present and eq(*contain, *boolTrue);
1274  }
1275  if (!present)
1276  continue;
1277  for (const auto &oset : othersets) {
1278  auto contain = oset->contains(fselement);
1279  if (not(eq(*contain, *boolTrue) or eq(*contain, *boolFalse))) {
1280  throw SymEngineException(
1281  "Not implemented Intersection class");
1282  }
1283  present = present and eq(*contain, *boolTrue);
1284  }
1285  if (present)
1286  finalfs.insert(fselement);
1287  }
1288  return finiteset(finalfs);
1289  }
1290 
1291  // If any of the sets is union, then return a Union of Intersections
1292  for (auto it = incopy.begin(); it != incopy.end(); ++it) {
1293  if (is_a<Union>(**it)) {
1294  auto container = down_cast<const Union &>(**it).get_container();
1295  incopy.erase(it);
1296  auto other = SymEngine::set_intersection(incopy);
1297  set_set usets;
1298  for (const auto &c : container) {
1299  usets.insert(SymEngine::set_intersection({c, other}));
1300  }
1301  return SymEngine::set_union(usets);
1302  }
1303  }
1304 
1305  // Simplify and return a `Complement` if any of the sets is a complement
1306  for (auto it = incopy.begin(); it != incopy.end(); ++it) {
1307  if (is_a<Complement>(**it)) {
1308  auto container
1309  = down_cast<const Complement &>(**it).get_container();
1310  auto universe = down_cast<const Complement &>(**it).get_universe();
1311  incopy.erase(it);
1312  incopy.insert(universe);
1313  auto other = SymEngine::set_intersection(incopy);
1314  return SymEngine::set_complement(other, container);
1315  }
1316  }
1317 
1318  // Pair-wise rules
1319  // TO-DO: needs the following improvement once Intersection
1320  // class is implemented.
1321  // input_oset if found to be not simplified, then skip this
1322  // pair.
1323  if (incopy.size() > 1) {
1324  auto temp = *incopy.begin();
1325  auto it = std::next(incopy.begin());
1326  for (; it != incopy.end(); ++it) {
1327  temp = temp->set_intersection(*it);
1328  }
1329  return temp;
1330  }
1331 
1332  if (incopy.size() == 1) {
1333  return *incopy.begin();
1334  } else {
1335  throw SymEngineException("Not implemented Intersection class");
1336  }
1337 }
1338 
1339 // helper to avoid redundant code
1340 RCP<const Set> set_complement_helper(const RCP<const Set> &container,
1341  const RCP<const Set> &universe)
1342 {
1343  if (is_a<Union>(*universe)) {
1344  auto univ = down_cast<const Union &>(*universe).get_container();
1345  set_set container_;
1346  for (auto &a : univ) {
1347  container_.insert(container->set_complement(a));
1348  }
1349  return SymEngine::set_union(container_);
1350  } else if (is_a<EmptySet>(*universe)) {
1351  return emptyset();
1352  } else if (is_a<FiniteSet>(*universe)) {
1353  const FiniteSet &other = down_cast<const FiniteSet &>(*universe);
1354  set_basic container_;
1355  set_basic rest;
1356  for (const auto &a : other.get_container()) {
1357  auto contain = container->contains(a);
1358  if (eq(*contain, *boolFalse)) {
1359  container_.insert(a);
1360  } else if (is_a<Contains>(*contain)) {
1361  rest.insert(a);
1362  }
1363  }
1364  if (rest.empty()) {
1365  return finiteset(container_);
1366  } else {
1367  return SymEngine::set_union(
1368  {finiteset(container_),
1369  make_rcp<const Complement>(finiteset(rest), container)});
1370  }
1371  }
1372  return make_rcp<const Complement>(universe, container);
1373 }
1374 
1375 RCP<const Set> set_complement(const RCP<const Set> &universe,
1376  const RCP<const Set> &container)
1377 {
1378  // represents universe - container
1379  return container->set_complement(universe);
1380 }
1381 
1382 RCP<const Set> conditionset(const RCP<const Basic> &sym,
1383  const RCP<const Boolean> &condition)
1384 {
1385  if (eq(*condition, *boolean(false))) {
1386  return emptyset();
1387  } else if (eq(*condition, *boolean(true))) {
1388  return universalset();
1389  }
1390  if (is_a<And>(*condition)) {
1391  auto cont = down_cast<const And &>(*condition).get_container();
1392  set_boolean newcont;
1393  set_basic present, others;
1394  for (auto it = cont.begin(); it != cont.end(); it++) {
1395  if (is_a<Contains>(**it)
1396  and eq(*down_cast<const Contains &>(**it).get_expr(), *sym)
1397  and is_a<FiniteSet>(
1398  *down_cast<const Contains &>(**it).get_set())) {
1399  auto fset = down_cast<const Contains &>(**it).get_set();
1400  auto fcont
1401  = down_cast<const FiniteSet &>(*fset).get_container();
1402  // use the result of simplification done in `logical_and()`
1403  for (const auto &elem : fcont) {
1404  if (not(is_a_Number(*elem) or is_a<Constant>(*elem))) {
1405  others.insert(elem);
1406  } else {
1407  // logical_and() doesn't guarantee that if element of a
1408  // finiteset is a number, then it satisfies other
1409  // conditions
1410  // it only assures that there doesn't exist any such
1411  // element of finiteset that surely fails in other
1412  // conditions.
1413  auto restCont = cont;
1414  restCont.erase(*it);
1415  auto restCond = logical_and(restCont);
1416  map_basic_basic d;
1417  d[sym] = elem;
1418  auto contain = restCond->subs(d);
1419  if (eq(*contain, *boolean(true))) {
1420  present.insert(elem);
1421  } else if (not eq(*contain, *boolean(false))) {
1422  others.insert(elem);
1423  } else {
1424  throw SymEngineException("element should have "
1425  "been removed within "
1426  "logical_and()");
1427  }
1428  }
1429  }
1430  } else {
1431  newcont.insert(*it);
1432  }
1433  }
1434  if (not present.empty()) {
1435  newcont.insert(finiteset(others)->contains(sym));
1436  return SymEngine::set_union(
1437  {finiteset(present), conditionset(sym, logical_and(newcont))});
1438  }
1439  }
1440  if (is_a<Contains>(*condition)) {
1441  return down_cast<const Contains &>(*condition).get_set();
1442  }
1443  return make_rcp<const ConditionSet>(sym, condition);
1444 }
1445 
1446 } // namespace SymEngine
Classes and functions relating to the binary operation of addition.
T begin(T... args)
RCP< const Basic > add(const RCP< const Basic > &a, const RCP< const Basic > &b)
Adds two objects (safely).
Definition: add.cpp:425
The lowest unit of symbolic representation.
Definition: basic.h:95
Basic()
Constructor.
Definition: basic.h:118
virtual bool __eq__(const Basic &o) const
Test equality.
Definition: sets.cpp:992
virtual int compare(const Basic &o) const
Definition: sets.cpp:1002
virtual hash_t __hash__() const
Definition: sets.cpp:984
virtual int compare(const Basic &o) const
Definition: sets.cpp:1078
virtual hash_t __hash__() const
Definition: sets.cpp:1060
virtual bool __eq__(const Basic &o) const
Test equality.
Definition: sets.cpp:1068
virtual hash_t __hash__() const
Definition: sets.cpp:585
virtual bool __eq__(const Basic &o) const
Test equality.
Definition: sets.cpp:593
virtual int compare(const Basic &o) const
Definition: sets.cpp:602
virtual int compare(const Basic &o) const
Definition: sets.cpp:1146
virtual bool __eq__(const Basic &o) const
Test equality.
Definition: sets.cpp:1136
virtual bool __eq__(const Basic &o) const
Test equality.
Definition: sets.cpp:889
virtual int compare(const Basic &o) const
Definition: sets.cpp:913
virtual vec_basic get_args() const
Returns the list of arguments.
Definition: sets.cpp:974
T empty(T... args)
T end(T... args)
T erase(T... args)
T insert(T... args)
T inserter(T... args)
T left(T... args)
T max(T... args)
T min(T... args)
Main namespace for SymEngine package.
Definition: add.cpp:19
bool is_a_Number(const Basic &b)
Definition: number.h:130
RCP< const Set > interval(const RCP< const Number > &start, const RCP< const Number > &end, const bool left_open=false, const bool right_open=false)
Definition: sets.h:475
RCP< const Boolean > Ge(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Convenience function returning LessThan object.
Definition: logic.cpp:683
std::enable_if< std::is_integral< T >::value, RCP< const Integer > >::type integer(T i)
Definition: integer.h:200
RCP< const Reals > reals()
Definition: sets.h:436
RCP< const Basic > max(const vec_basic &arg)
Canonicalize Max:
Definition: functions.cpp:3512
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:707
RCP< const EmptySet > emptyset()
Definition: sets.h:454
RCP< const Basic > ceiling(const RCP< const Basic > &arg)
Canonicalize Ceiling:
Definition: functions.cpp:662
RCP< const Integers > integers()
Definition: sets.h:448
RCP< const UniversalSet > universalset()
Definition: sets.h:460
RCP< const Basic > floor(const RCP< const Basic > &arg)
Canonicalize Floor:
Definition: functions.cpp:568
RCP< const Set > conditionset(const RCP< const Basic > &sym, const RCP< const Boolean > &condition)
Definition: sets.cpp:1382
RCP< const Boolean > Eq(const RCP< const Basic > &lhs)
Returns the canonicalized Equality object from a single argument.
Definition: logic.cpp:592
RCP< const Set > finiteset(const set_basic &container)
Definition: sets.h:466
int unified_compare(const T &a, const T &b)
Definition: dict.h:205
bool neq(const Basic &a, const Basic &b)
Checks inequality for a and b
Definition: basic-inl.h:29
RCP< const Rationals > rationals()
Definition: sets.h:442
T next(T... args)
T push_back(T... args)
T set_difference(T... args)
T set_intersection(T... args)
T set_union(T... args)
T size(T... args)