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 static RCP<const Set> make_set_union(const set_set &in)
116 {
117  if (in.size() > 1) {
118  return make_rcp<const Union>(in);
119  }
120  return *in.begin();
121 }
122 
123 static RCP<const Set> make_set_intersection(const set_set &in)
124 {
125  if (in.size() > 1) {
126  return make_rcp<const Intersection>(in);
127  }
128  return *in.begin();
129 }
130 
131 RCP<const Set> Interval::set_intersection(const RCP<const Set> &o) const
132 {
133  if (is_a<Interval>(*o)) {
134  const Interval &other = down_cast<const Interval &>(*o);
135  RCP<const Number> start, end;
136  bool left_open, right_open;
137  RCP<const Basic> start_end, end_start;
138  start_end = min({this->start_, other.end_});
139  end_start = min({this->end_, other.start_});
140 
141  if (eq(*this->start_, *start_end) and eq(*other.start_, *end_start)) {
142  RCP<const Basic> start_start, end_end;
143  start_start = min({this->start_, other.start_});
144  end_end = min({this->end_, other.end_});
145  if (neq(*this->start_, *other.start_)) {
146  if (eq(*this->start_, *start_start)) {
147  start = other.start_;
148  left_open = other.left_open_;
149  } else {
150  start = this->start_;
151  left_open = this->left_open_;
152  }
153  } else {
154  start = this->start_;
155  left_open = this->left_open_ or other.left_open_;
156  }
157 
158  if (neq(*this->end_, *other.end_)) {
159  if (eq(*this->end_, *end_end)) {
160  end = this->end_;
161  right_open = this->right_open_;
162  } else {
163  end = other.end_;
164  right_open = other.right_open_;
165  }
166  } else {
167  end = this->end_;
168  right_open = this->right_open_ or other.right_open_;
169  }
170  return interval(start, end, left_open, right_open);
171  } else {
172  return emptyset();
173  }
174  }
175  if (is_a<Integers>(*o) or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
176  if (is_a_Number(*start_) and is_a_Number(*end_)) {
177  auto first = SymEngine::ceiling(start_);
178  auto last = SymEngine::floor(end_);
179  if (is_a<Naturals>(*o)
180  and not down_cast<const Integer &>(*first).is_positive()) {
181  first = integer(1);
182  } else if (is_a<Naturals0>(*o)
183  and down_cast<const Integer &>(*first).is_negative()) {
184  first = integer(0);
185  }
186  if (eq(*first, *start_) and left_open_) {
187  first = add(first, integer(1));
188  }
189  if (eq(*last, *end_) and right_open_) {
190  last = add(last, integer(-1));
191  }
192  if (eq(*Lt(last, first), *boolTrue)) {
193  return emptyset();
194  }
195  set_basic container;
196  while (eq(*Ge(last, first), *boolTrue)) {
197  container.insert(first);
198  first = add(first, integer(1));
199  }
200  return finiteset(container);
201  } else {
202  return SymEngine::set_intersection(
203  {rcp_from_this_cast<const Set>(), o});
204  }
205  }
206  if (is_a<UniversalSet>(*o) or is_a<EmptySet>(*o) or is_a<FiniteSet>(*o)
207  or is_a<Union>(*o) or is_a<Rationals>(*o) or is_a<Reals>(*o)
208  or is_a<Complexes>(*o)) {
209  return (*o).set_intersection(rcp_from_this_cast<const Set>());
210  }
211  return make_set_intersection({rcp_from_this_cast<const Set>(), o});
212 }
213 
214 RCP<const Set> Interval::set_union(const RCP<const Set> &o) const
215 {
216  if (is_a<Interval>(*o)) {
217  const Interval &other = down_cast<const Interval &>(*o);
218  RCP<const Basic> start_start, end_end, m;
219  RCP<const Number> start, end;
220  bool left_open, right_open;
221  start_start = max({this->start_, other.start_});
222  end_end = min({this->end_, other.end_});
223  m = min({start_start, end_end});
224  if ((eq(*end_end, *start_start) and eq(*end_end, *m)
225  and ((eq(*end_end, *this->end_) and this->right_open_)
226  or (eq(*end_end, *other.end_) and other.right_open_)))
227  or (eq(*end_end, *m) and not eq(*end_end, *start_start))) {
228  return SymEngine::make_set_union(
229  {rcp_from_this_cast<const Set>(), o});
230  } else {
231  if (eq(*min({this->start_, other.start_}), *this->start_)) {
232  start = this->start_;
233  } else {
234  start = other.start_;
235  }
236  if (eq(*max({this->end_, other.end_}), *this->end_)) {
237  end = this->end_;
238  } else {
239  end = other.end_;
240  }
241  left_open = ((neq(*this->start_, *start) or this->left_open_)
242  and (neq(*other.start_, *start) or other.left_open_));
243  right_open = ((neq(*this->end_, *end) or this->right_open_)
244  and (neq(*other.end_, *end) or other.right_open_));
245  return interval(start, end, left_open, right_open);
246  }
247  }
248  if (is_a<UniversalSet>(*o) or is_a<EmptySet>(*o) or is_a<FiniteSet>(*o)
249  or is_a<Union>(*o) or is_a<Complexes>(*o) or is_a<Reals>(*o)
250  or is_a<Rationals>(*o) or is_a<Integers>(*o) or is_a<Naturals>(*o)
251  or is_a<Naturals0>(*o)) {
252  return (*o).set_union(rcp_from_this_cast<const Set>());
253  }
254  return SymEngine::make_set_union({rcp_from_this_cast<const Set>(), o});
255 }
256 
257 RCP<const Set> Interval::set_complement(const RCP<const Set> &o) const
258 {
259  if (is_a<Interval>(*o)) {
260  set_set cont;
261  const Interval &other = down_cast<const Interval &>(*o);
262  if (eq(*max({start_, other.start_}), *start_)) {
263  cont.insert(interval(other.get_start(), start_,
264  other.get_left_open(), not left_open_));
265  }
266  if (eq(*min({end_, other.end_}), *end_)) {
267  cont.insert(interval(end_, other.get_end(), not right_open_,
268  other.get_right_open()));
269  }
270  return SymEngine::set_union(cont);
271  }
272  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
273 }
274 
275 vec_basic Interval::get_args() const
276 {
277  return {start_, end_, boolean(left_open_), boolean(right_open_)};
278 }
279 
280 RCP<const Set> Complexes::set_intersection(const RCP<const Set> &o) const
281 {
282  if (is_a<Interval>(*o) or is_a<EmptySet>(*o) or is_a<Complexes>(*o)
283  or is_a<Reals>(*o) or is_a<Rationals>(*o) or is_a<Integers>(*o)
284  or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
285  return o;
286  } else if (is_a<FiniteSet>(*o)) {
287  return (*o).set_intersection(rcp_from_this_cast<const Set>());
288  } else {
289  return SymEngine::set_intersection(
290  {rcp_from_this_cast<const Set>(), o});
291  }
292 }
293 
294 RCP<const Set> Complexes::set_union(const RCP<const Set> &o) const
295 {
296  if (is_a<Interval>(*o) or is_a<EmptySet>(*o) or is_a<Complexes>(*o)
297  or is_a<Reals>(*o) or is_a<Integers>(*o) or is_a<Rationals>(*o)
298  or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
299  return complexes();
300  } else if (is_a<FiniteSet>(*o)) {
301  return (*o).set_union(rcp_from_this_cast<const Set>());
302  } else {
303  return SymEngine::set_union({rcp_from_this_cast<const Set>(), o});
304  }
305 }
306 
307 RCP<const Set> Complexes::set_complement(const RCP<const Set> &o) const
308 {
309  if (is_a<EmptySet>(*o) or is_a<Complexes>(*o) or is_a<Reals>(*o)
310  or is_a<Rationals>(*o) or is_a<Integers>(*o) or is_a<Interval>(*o)
311  or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
312  return emptyset();
313  }
314  if (is_a<UniversalSet>(*o)) {
315  return make_rcp<const Complement>(o, complexes());
316  }
317  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
318 }
319 
320 RCP<const Boolean> Complexes::contains(const RCP<const Basic> &a) const
321 {
322  if (not is_a_Number(*a)) {
323  if (is_a_Set(*a)) {
324  return boolean(false);
325  } else {
326  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
327  }
328  }
329  return boolean(true);
330 }
331 
332 hash_t Complexes::__hash__() const
333 {
334  hash_t seed = SYMENGINE_COMPLEXES;
335  return seed;
336 }
337 
338 bool Complexes::__eq__(const Basic &o) const
339 {
340  if (is_a<Complexes>(o))
341  return true;
342  return false;
343 }
344 
345 int Complexes::compare(const Basic &o) const
346 {
347  SYMENGINE_ASSERT(is_a<Complexes>(o))
348  return 0;
349 }
350 
351 const RCP<const Complexes> &Complexes::getInstance()
352 {
353  const static auto a = make_rcp<const Complexes>();
354  return a;
355 }
356 
357 RCP<const Set> Reals::set_intersection(const RCP<const Set> &o) const
358 {
359  if (is_a<Interval>(*o) or is_a<EmptySet>(*o) or is_a<Reals>(*o)
360  or is_a<Rationals>(*o) or is_a<Integers>(*o) or is_a<Naturals>(*o)
361  or is_a<Naturals0>(*o)) {
362  return o;
363  } else if (is_a<FiniteSet>(*o) or is_a<Complexes>(*o)) {
364  return (*o).set_intersection(rcp_from_this_cast<const Set>());
365  } else {
366  return SymEngine::set_intersection(
367  {rcp_from_this_cast<const Set>(), o});
368  }
369 }
370 
371 RCP<const Set> Reals::set_union(const RCP<const Set> &o) const
372 {
373  if (is_a<Interval>(*o) or is_a<EmptySet>(*o) or is_a<Reals>(*o)
374  or is_a<Integers>(*o) or is_a<Rationals>(*o) or is_a<Naturals>(*o)
375  or is_a<Naturals0>(*o)) {
376  return reals();
377  } else if (is_a<FiniteSet>(*o) or is_a<Complexes>(*o)) {
378  return (*o).set_union(rcp_from_this_cast<const Set>());
379  } else {
380  return SymEngine::set_union({rcp_from_this_cast<const Set>(), o});
381  }
382 }
383 
384 RCP<const Set> Reals::set_complement(const RCP<const Set> &o) const
385 {
386  if (is_a<EmptySet>(*o) or is_a<Reals>(*o) or is_a<Rationals>(*o)
387  or is_a<Integers>(*o) or is_a<Interval>(*o) or is_a<Naturals>(*o)
388  or is_a<Naturals0>(*o)) {
389  return emptyset();
390  }
391  if (is_a<UniversalSet>(*o) or is_a<Complexes>(*o)) {
392  return make_rcp<const Complement>(o, reals());
393  }
394  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
395 }
396 
397 RCP<const Boolean> Reals::contains(const RCP<const Basic> &a) const
398 {
399  if (not is_a_Number(*a)) {
400  if (is_a_Set(*a)) {
401  return boolean(false);
402  } else {
403  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
404  }
405  }
406  if (is_a<Complex>(*a)) {
407  return boolean(false);
408  }
409  return boolean(true);
410 }
411 
412 hash_t Reals::__hash__() const
413 {
414  hash_t seed = SYMENGINE_REALS;
415  return seed;
416 }
417 
418 bool Reals::__eq__(const Basic &o) const
419 {
420  if (is_a<Reals>(o))
421  return true;
422  return false;
423 }
424 
425 int Reals::compare(const Basic &o) const
426 {
427  SYMENGINE_ASSERT(is_a<Reals>(o))
428  return 0;
429 }
430 
431 const RCP<const Reals> &Reals::getInstance()
432 {
433  const static auto a = make_rcp<const Reals>();
434  return a;
435 }
436 
437 RCP<const Set> Rationals::set_intersection(const RCP<const Set> &o) const
438 {
439  if (is_a<EmptySet>(*o) or is_a<Rationals>(*o) or is_a<Integers>(*o)
440  or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
441  return o;
442  } else if (is_a<FiniteSet>(*o) or is_a<Reals>(*o) or is_a<Complexes>(*o)) {
443  return (*o).set_intersection(rcp_from_this_cast<const Set>());
444  } else {
445  return SymEngine::set_intersection(
446  {rcp_from_this_cast<const Set>(), o});
447  }
448 }
449 
450 RCP<const Set> Rationals::set_union(const RCP<const Set> &o) const
451 {
452  if (is_a<EmptySet>(*o) or is_a<Integers>(*o) or is_a<Rationals>(*o)
453  or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
454  return rationals();
455  } else if (is_a<FiniteSet>(*o) or is_a<Reals>(*o) or is_a<Complexes>(*o)) {
456  return (*o).set_union(rcp_from_this_cast<const Set>());
457  } else {
458  return SymEngine::set_union({rcp_from_this_cast<const Set>(), o});
459  }
460 }
461 
462 RCP<const Set> Rationals::set_complement(const RCP<const Set> &o) const
463 {
464  if (is_a<EmptySet>(*o) or is_a<Rationals>(*o) or is_a<Integers>(*o)
465  or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
466  return emptyset();
467  }
468  if (is_a<UniversalSet>(*o) or is_a<Complexes>(*o) or is_a<Reals>(*o)
469  or is_a<Interval>(*o)) {
470  return make_rcp<const Complement>(o, rationals());
471  }
472  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
473 }
474 
475 RCP<const Boolean> Rationals::contains(const RCP<const Basic> &a) const
476 {
477  if (not is_a_Number(*a)) {
478  if (is_a_Set(*a)) {
479  return boolean(false);
480  } else {
481  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
482  }
483  }
484  if (is_a<Complex>(*a) or not down_cast<const Number &>(*a).is_exact()) {
485  return boolean(false);
486  }
487  return boolean(true);
488 }
489 
490 hash_t Rationals::__hash__() const
491 {
492  hash_t seed = SYMENGINE_RATIONALS;
493  return seed;
494 }
495 
496 bool Rationals::__eq__(const Basic &o) const
497 {
498  return (is_a<Rationals>(o));
499 }
500 
501 int Rationals::compare(const Basic &o) const
502 {
503  SYMENGINE_ASSERT(is_a<Rationals>(o))
504  return 0;
505 }
506 
507 const RCP<const Rationals> &Rationals::getInstance()
508 {
509  const static auto a = make_rcp<const Rationals>();
510  return a;
511 }
512 
513 RCP<const Set> Integers::set_intersection(const RCP<const Set> &o) const
514 {
515  if (is_a<EmptySet>(*o) or is_a<Integers>(*o) or is_a<Naturals>(*o)
516  or is_a<Naturals0>(*o)) {
517  return o;
518  } else if (is_a<Complexes>(*o) or is_a<Reals>(*o) or is_a<Rationals>(*o)) {
519  return integers();
520  } else if (is_a<FiniteSet>(*o) or is_a<Interval>(*o)) {
521  return (*o).set_intersection(rcp_from_this_cast<const Set>());
522  } else {
523  return SymEngine::set_intersection(
524  {rcp_from_this_cast<const Set>(), o});
525  }
526 }
527 
528 RCP<const Set> Integers::set_union(const RCP<const Set> &o) const
529 {
530  if (is_a<Integers>(*o) or is_a<EmptySet>(*o) or is_a<Naturals>(*o)
531  or is_a<Naturals0>(*o)) {
532  return integers();
533  } else if (is_a<Complexes>(*o)) {
534  return complexes();
535  } else if (is_a<Reals>(*o)) {
536  return reals();
537  } else if (is_a<Rationals>(*o)) {
538  return rationals();
539  } else if (is_a<FiniteSet>(*o)) {
540  return (*o).set_union(rcp_from_this_cast<const Set>());
541  } else if (is_a<UniversalSet>(*o)) {
542  return universalset();
543  } else {
544  return SymEngine::make_set_union({rcp_from_this_cast<const Set>(), o});
545  }
546 }
547 
548 RCP<const Set> Integers::set_complement(const RCP<const Set> &o) const
549 {
550  if (is_a<EmptySet>(*o) or is_a<Integers>(*o) or is_a<Naturals>(*o)
551  or is_a<Naturals0>(*o)) {
552  return emptyset();
553  }
554  if (is_a<UniversalSet>(*o) or is_a<Rationals>(*o) or is_a<Reals>(*o)
555  or is_a<Complexes>(*o)) {
556  return make_rcp<const Complement>(o, integers());
557  }
558  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
559 }
560 
561 RCP<const Boolean> Integers::contains(const RCP<const Basic> &a) const
562 {
563  if (not is_a_Number(*a)) {
564  if (is_a_Set(*a)) {
565  return boolean(false);
566  } else {
567  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
568  }
569  }
570  if (is_a<Integer>(*a)) {
571  return boolean(true);
572  }
573  return boolean(false);
574 }
575 
576 hash_t Integers::__hash__() const
577 {
578  hash_t seed = SYMENGINE_INTEGERS;
579  return seed;
580 }
581 
582 bool Integers::__eq__(const Basic &o) const
583 {
584  if (is_a<Integers>(o))
585  return true;
586  return false;
587 }
588 
589 int Integers::compare(const Basic &o) const
590 {
591  SYMENGINE_ASSERT(is_a<Integers>(o))
592  return 0;
593 }
594 
595 const RCP<const Integers> &Integers::getInstance()
596 {
597  const static auto a = make_rcp<const Integers>();
598  return a;
599 }
600 
601 RCP<const Set> Naturals::set_intersection(const RCP<const Set> &o) const
602 {
603  if (is_a<EmptySet>(*o) or is_a<Naturals>(*o)) {
604  return o;
605  } else if (is_a<Naturals0>(*o) or is_a<Integers>(*o) or is_a<Complexes>(*o)
606  or is_a<Reals>(*o) or is_a<Rationals>(*o)) {
607  return naturals();
608  } else if (is_a<FiniteSet>(*o) or is_a<Interval>(*o)) {
609  return (*o).set_intersection(rcp_from_this_cast<const Set>());
610  } else {
611  return SymEngine::set_intersection(
612  {rcp_from_this_cast<const Set>(), o});
613  }
614 }
615 
616 RCP<const Set> Naturals::set_union(const RCP<const Set> &o) const
617 {
618  if (is_a<EmptySet>(*o)) {
619  return naturals();
620  } else if (is_a<Naturals>(*o) or is_a<Naturals0>(*o) or is_a<Integers>(*o)
621  or is_a<Complexes>(*o) or is_a<Reals>(*o) or is_a<Rationals>(*o)
622  or is_a<UniversalSet>(*o)) {
623  return o;
624  } else if (is_a<FiniteSet>(*o)) {
625  return (*o).set_union(rcp_from_this_cast<const Set>());
626  } else {
627  return SymEngine::make_set_union({rcp_from_this_cast<const Set>(), o});
628  }
629 }
630 
631 RCP<const Set> Naturals::set_complement(const RCP<const Set> &o) const
632 {
633  if (is_a<EmptySet>(*o) or is_a<Naturals>(*o)) {
634  return emptyset();
635  }
636  if (is_a<Naturals0>(*o)) {
637  finiteset({zero});
638  }
639  if (is_a<UniversalSet>(*o) or is_a<Integers>(*o) or is_a<Rationals>(*o)
640  or is_a<Reals>(*o) or is_a<Complexes>(*o)) {
641  return make_rcp<const Complement>(o, naturals());
642  }
643  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
644 }
645 
646 RCP<const Boolean> Naturals::contains(const RCP<const Basic> &a) const
647 {
648  if (not is_a_Number(*a)) {
649  if (is_a_Set(*a)) {
650  return boolean(false);
651  } else {
652  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
653  }
654  } else if (is_a<Integer>(*a)
655  and down_cast<const Integer &>(*a).is_positive()) {
656  return boolean(true);
657  } else {
658  return boolean(false);
659  }
660 }
661 
662 hash_t Naturals::__hash__() const
663 {
664  hash_t seed = SYMENGINE_NATURALS;
665  return seed;
666 }
667 
668 bool Naturals::__eq__(const Basic &o) const
669 {
670  if (is_a<Naturals>(o))
671  return true;
672  return false;
673 }
674 
675 int Naturals::compare(const Basic &o) const
676 {
677  SYMENGINE_ASSERT(is_a<Naturals>(o))
678  return 0;
679 }
680 
681 const RCP<const Naturals> &Naturals::getInstance()
682 {
683  const static auto a = make_rcp<const Naturals>();
684  return a;
685 }
686 
687 RCP<const Set> Naturals0::set_intersection(const RCP<const Set> &o) const
688 {
689  if (is_a<EmptySet>(*o) or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
690  return o;
691  } else if (is_a<Integers>(*o) or is_a<Complexes>(*o) or is_a<Reals>(*o)
692  or is_a<Rationals>(*o)) {
693  return naturals0();
694  } else if (is_a<FiniteSet>(*o) or is_a<Interval>(*o)) {
695  return (*o).set_intersection(rcp_from_this_cast<const Set>());
696  } else {
697  return SymEngine::set_intersection(
698  {rcp_from_this_cast<const Set>(), o});
699  }
700 }
701 
702 RCP<const Set> Naturals0::set_union(const RCP<const Set> &o) const
703 {
704  if (is_a<EmptySet>(*o) or is_a<Naturals>(*o)) {
705  return naturals0();
706  } else if (is_a<Naturals0>(*o) or is_a<Integers>(*o) or is_a<Complexes>(*o)
707  or is_a<Reals>(*o) or is_a<Rationals>(*o)
708  or is_a<UniversalSet>(*o)) {
709  return o;
710  } else if (is_a<FiniteSet>(*o)) {
711  return (*o).set_union(rcp_from_this_cast<const Set>());
712  } else {
713  return SymEngine::make_set_union({rcp_from_this_cast<const Set>(), o});
714  }
715 }
716 
717 RCP<const Set> Naturals0::set_complement(const RCP<const Set> &o) const
718 {
719  if (is_a<EmptySet>(*o) or is_a<Naturals0>(*o) or is_a<Naturals>(*o)) {
720  return emptyset();
721  }
722  if (is_a<UniversalSet>(*o) or is_a<Integers>(*o) or is_a<Rationals>(*o)
723  or is_a<Reals>(*o) or is_a<Complexes>(*o)) {
724  return make_rcp<const Complement>(o, naturals());
725  }
726  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
727 }
728 
729 RCP<const Boolean> Naturals0::contains(const RCP<const Basic> &a) const
730 {
731  if (not is_a_Number(*a)) {
732  if (is_a_Set(*a)) {
733  return boolean(false);
734  } else {
735  return make_rcp<Contains>(a, rcp_from_this_cast<const Set>());
736  }
737  } else if (is_a<Integer>(*a)
738  and (not down_cast<const Integer &>(*a).is_negative())) {
739  return boolean(true);
740  } else {
741  return boolean(false);
742  }
743 }
744 
745 hash_t Naturals0::__hash__() const
746 {
747  hash_t seed = SYMENGINE_NATURALS0;
748  return seed;
749 }
750 
751 bool Naturals0::__eq__(const Basic &o) const
752 {
753  if (is_a<Naturals0>(o))
754  return true;
755  return false;
756 }
757 
758 int Naturals0::compare(const Basic &o) const
759 {
760  SYMENGINE_ASSERT(is_a<Naturals0>(o))
761  return 0;
762 }
763 
764 const RCP<const Naturals0> &Naturals0::getInstance()
765 {
766  const static auto a = make_rcp<const Naturals0>();
767  return a;
768 }
769 
770 RCP<const Set> EmptySet::set_intersection(const RCP<const Set> &o) const
771 {
772  return emptyset();
773 }
774 
775 RCP<const Set> EmptySet::set_union(const RCP<const Set> &o) const
776 {
777  return o;
778 }
779 
780 RCP<const Set> EmptySet::set_complement(const RCP<const Set> &o) const
781 {
782  return o;
783 }
784 
785 hash_t EmptySet::__hash__() const
786 {
787  hash_t seed = SYMENGINE_EMPTYSET;
788  return seed;
789 }
790 
791 bool EmptySet::__eq__(const Basic &o) const
792 {
793  if (is_a<EmptySet>(o))
794  return true;
795  return false;
796 }
797 
798 int EmptySet::compare(const Basic &o) const
799 {
800  SYMENGINE_ASSERT(is_a<EmptySet>(o))
801  return 0;
802 }
803 
804 const RCP<const EmptySet> &EmptySet::getInstance()
805 {
806  const static auto a = make_rcp<const EmptySet>();
807  return a;
808 }
809 
810 RCP<const Set> UniversalSet::set_intersection(const RCP<const Set> &o) const
811 {
812  return o;
813 }
814 
815 RCP<const Set> UniversalSet::set_union(const RCP<const Set> &o) const
816 {
817  return universalset();
818 }
819 
820 RCP<const Set> UniversalSet::set_complement(const RCP<const Set> &o) const
821 {
822  return emptyset();
823 }
824 
825 hash_t UniversalSet::__hash__() const
826 {
827  hash_t seed = SYMENGINE_UNIVERSALSET;
828  return seed;
829 }
830 
831 bool UniversalSet::__eq__(const Basic &o) const
832 {
833  if (is_a<UniversalSet>(o))
834  return true;
835  return false;
836 }
837 
838 int UniversalSet::compare(const Basic &o) const
839 {
840  SYMENGINE_ASSERT(is_a<UniversalSet>(o))
841  return 0;
842 }
843 
844 const RCP<const UniversalSet> &UniversalSet::getInstance()
845 {
846  const static auto a = make_rcp<const UniversalSet>();
847  return a;
848 }
849 
850 FiniteSet::FiniteSet(const set_basic &container) : container_(container)
851 {
852  SYMENGINE_ASSIGN_TYPEID()
853  SYMENGINE_ASSERT(FiniteSet::is_canonical(container_));
854 }
855 
856 bool FiniteSet::is_canonical(const set_basic &container)
857 {
858  return container.size() != 0;
859 }
860 
861 hash_t FiniteSet::__hash__() const
862 {
863  hash_t seed = SYMENGINE_FINITESET;
864  for (const auto &a : container_)
865  hash_combine<Basic>(seed, *a);
866  return seed;
867 }
868 
869 bool FiniteSet::__eq__(const Basic &o) const
870 {
871  if (is_a<FiniteSet>(o)) {
872  const FiniteSet &other = down_cast<const FiniteSet &>(o);
873  return unified_eq(container_, other.container_);
874  }
875  return false;
876 }
877 
878 int FiniteSet::compare(const Basic &o) const
879 {
880  // compares two FiniteSet based on their length
881  SYMENGINE_ASSERT(is_a<FiniteSet>(o))
882  const FiniteSet &other = down_cast<const FiniteSet &>(o);
883  return unified_compare(container_, other.container_);
884 }
885 
886 RCP<const Boolean> FiniteSet::contains(const RCP<const Basic> &a) const
887 {
888  set_basic rest;
889  for (const auto &elem : container_) {
890  auto cont = Eq(elem, a);
891  if (eq(*cont, *boolTrue))
892  return boolTrue;
893  if (not eq(*cont, *boolFalse))
894  rest.insert(elem);
895  }
896  if (rest.empty()) {
897  return boolFalse;
898  } else {
899  return make_rcp<Contains>(a, finiteset(rest));
900  }
901 }
902 
903 RCP<const Set> FiniteSet::set_union(const RCP<const Set> &o) const
904 {
905  if (is_a<FiniteSet>(*o)) {
906  const FiniteSet &other = down_cast<const FiniteSet &>(*o);
907  set_basic container;
908  std::set_union(container_.begin(), container_.end(),
909  other.container_.begin(), other.container_.end(),
910  std::inserter(container, container.begin()),
911  RCPBasicKeyLess{});
912  return finiteset(container);
913  }
914  if (is_a<Interval>(*o)) {
915  set_basic container;
916  const Interval &other = down_cast<const Interval &>(*o);
917  bool left = other.get_left_open(), right = other.get_right_open();
918  for (const auto &a : container_) {
919  auto contain = o->contains(a);
920  if (eq(*contain, *boolFalse)) {
921  if (left)
922  if (eq(*other.get_start(), *a)) {
923  left = false;
924  continue;
925  }
926  if (right)
927  if (eq(*other.get_end(), *a)) {
928  right = false;
929  continue;
930  }
931  container.insert(a);
932  } else if (is_a<Contains>(*contain)) {
933  container.insert(a);
934  }
935  }
936  if (not container.empty()) {
937  if (left == other.get_left_open()
938  and right == other.get_right_open()) {
939  return SymEngine::make_set_union({finiteset(container), o});
940  } else {
941  return SymEngine::make_set_union(
942  set_set({finiteset(container),
943  interval(other.get_start(), other.get_end(), left,
944  right)}));
945  }
946  } else {
947  if (left == other.get_left_open()
948  and right == other.get_right_open()) {
949  return o;
950  } else {
951  return interval(other.get_start(), other.get_end(), left,
952  right);
953  }
954  }
955  }
956  if (is_a<Complexes>(*o)) {
957  set_basic container;
958  for (const auto &elem : container_) {
959  if (!is_a_Number(*elem)) {
960  container.insert(elem);
961  }
962  }
963  if (container.empty()) {
964  return complexes();
965  } else {
966  return SymEngine::make_set_union(
967  {complexes(), finiteset(container)});
968  }
969  }
970  if (is_a<Reals>(*o)) {
971  set_basic container;
972  for (const auto &elem : container_) {
973  if (!is_a_Number(*elem)
974  || down_cast<const Number &>(*elem).is_complex()) {
975  container.insert(elem);
976  }
977  }
978  if (container.empty()) {
979  return reals();
980  } else {
981  return SymEngine::make_set_union({reals(), finiteset(container)});
982  }
983  }
984  if (is_a<Rationals>(*o)) {
985  set_basic container;
986  for (const auto &elem : container_) {
987  if (!is_a_Number(*elem)
988  || down_cast<const Number &>(*elem).is_complex()) {
989  container.insert(elem);
990  }
991  }
992  if (container.empty()) {
993  return rationals();
994  } else {
995  return SymEngine::make_set_union(
996  {rationals(), finiteset(container)});
997  }
998  }
999  if (is_a<Integers>(*o) or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
1000  set_basic container;
1001  for (const auto &elem : container_) {
1002  if (is_a<Integers>(*o)) {
1003  if (not is_a<Integer>(*elem)) {
1004  container.insert(elem);
1005  }
1006  } else if (is_a<Naturals>(*o)) {
1007  if (not(is_a<Integer>(*elem)
1008  and down_cast<const Integer &>(*elem).is_positive())) {
1009  container.insert(elem);
1010  }
1011  } else {
1012  if (not(is_a<Integer>(*elem)
1013  and not down_cast<const Integer &>(*elem)
1014  .is_negative())) {
1015  container.insert(elem);
1016  }
1017  }
1018  }
1019  if (container.empty()) {
1020  return o;
1021  } else {
1022  return SymEngine::make_set_union({o, finiteset(container)});
1023  }
1024  }
1025  if (is_a<UniversalSet>(*o) or is_a<EmptySet>(*o) or is_a<Union>(*o)) {
1026  return (*o).set_union(rcp_from_this_cast<const Set>());
1027  }
1028  return SymEngine::make_set_union({rcp_from_this_cast<const Set>(), o});
1029 }
1030 
1031 RCP<const Set> FiniteSet::set_intersection(const RCP<const Set> &o) const
1032 {
1033  if (is_a<FiniteSet>(*o)) {
1034  return SymEngine::set_intersection(
1035  {rcp_from_this_cast<const Set>(), o});
1036  }
1037  if (is_a<Interval>(*o)) {
1038  set_basic container;
1039  for (const auto &a : container_) {
1040  auto contain = o->contains(a);
1041  if (eq(*contain, *boolTrue))
1042  container.insert(a);
1043  if (is_a<Contains>(*contain))
1044  return make_set_intersection(
1045  {rcp_from_this_cast<const Set>(), o});
1046  }
1047  return finiteset(container);
1048  }
1049  if (is_a<Complexes>(*o) or is_a<Reals>(*o) or is_a<Rationals>(*o)) {
1050  set_basic kept;
1051  set_basic others;
1052  for (const auto &elem : container_) {
1053  if (is_a_Number(*elem)) {
1054  if (!down_cast<const Number &>(*elem).is_complex()) {
1055  if (!is_a<Rationals>(*o)
1056  or down_cast<const Number &>(*elem).is_exact()) {
1057  kept.insert(elem);
1058  }
1059  } else {
1060  if (is_a<Complexes>(*o)) {
1061  kept.insert(elem);
1062  }
1063  }
1064  } else {
1065  others.insert(elem);
1066  }
1067  }
1068  if (kept.empty()) {
1069  if (others.empty()) {
1070  return emptyset();
1071  } else {
1072  return SymEngine::make_set_intersection({o, finiteset(others)});
1073  }
1074  } else {
1075  if (others.empty()) {
1076  return finiteset(kept);
1077  } else {
1078  others.insert(kept.begin(), kept.end());
1079  return SymEngine::make_set_intersection({o, finiteset(others)});
1080  }
1081  }
1082  }
1083  if (is_a<Integers>(*o) or is_a<Naturals>(*o) or is_a<Naturals0>(*o)) {
1084  set_basic kept_integers;
1085  set_basic others;
1086  for (const auto &elem : container_) {
1087  if (is_a_Number(*elem)) {
1088  if (is_a<Integers>(*o) and is_a<Integer>(*elem)) {
1089  kept_integers.insert(elem);
1090  } else if (is_a<Naturals>(*o) and is_a<Integer>(*elem)
1091  and down_cast<const Integer &>(*elem)
1092  .is_positive()) {
1093  kept_integers.insert(elem);
1094  } else if (is_a<Naturals0>(*o) and is_a<Integer>(*elem)
1095  and (not down_cast<const Integer &>(*elem)
1096  .is_negative())) {
1097  kept_integers.insert(elem);
1098  }
1099  } else {
1100  others.insert(elem);
1101  }
1102  }
1103  if (kept_integers.empty()) {
1104  if (others.empty()) {
1105  return emptyset();
1106  } else {
1107  return SymEngine::make_set_intersection(
1108  {integers(), finiteset(others)});
1109  }
1110  } else {
1111  if (others.empty()) {
1112  return finiteset(kept_integers);
1113  } else {
1114  others.insert(kept_integers.begin(), kept_integers.end());
1115  return SymEngine::make_set_intersection(
1116  {integers(), finiteset(others)});
1117  }
1118  }
1119  }
1120  if (is_a<UniversalSet>(*o) or is_a<EmptySet>(*o) or is_a<Union>(*o)) {
1121  return (*o).set_intersection(rcp_from_this_cast<const Set>());
1122  }
1123  return make_set_intersection({rcp_from_this_cast<const Set>(), o});
1124 }
1125 
1126 RCP<const Set> FiniteSet::set_complement(const RCP<const Set> &o) const
1127 {
1128  if (is_a<FiniteSet>(*o)) {
1129  const FiniteSet &other = down_cast<const FiniteSet &>(*o);
1130  set_basic container;
1131  std::set_difference(other.container_.begin(), other.container_.end(),
1132  container_.begin(), container_.end(),
1133  std::inserter(container, container.begin()),
1134  RCPBasicKeyLess{});
1135  return finiteset(container);
1136  }
1137 
1138  if (is_a<Interval>(*o)) {
1139  set_set intervals;
1140  auto &other = down_cast<const Interval &>(*o);
1141  RCP<const Number> last = other.get_start();
1142  RCP<const Number> a_num;
1143  set_basic rest;
1144  bool left_open = other.get_left_open(),
1145  right_open = other.get_right_open();
1146  for (auto it = container_.begin(); it != container_.end(); it++) {
1147  if (eq(*max({*it, other.get_start()}), *other.get_start())) {
1148  if (eq(**it, *other.get_start()))
1149  left_open = true;
1150  continue;
1151  }
1152  if (eq(*max({*it, other.get_end()}), **it)) {
1153  if (eq(**it, *other.get_end()))
1154  right_open = true;
1155  break;
1156  }
1157  if (is_a_Number(**it)) {
1158  a_num = rcp_static_cast<const Number>(*it);
1159  intervals.insert(interval(last, a_num, left_open, true));
1160  last = a_num;
1161  left_open = true;
1162  } else {
1163  rest.insert(*it);
1164  }
1165  }
1166 
1167  if (eq(*max({last, other.get_end()}), *other.get_end())) {
1168  intervals.insert(
1169  interval(last, other.get_end(), left_open, right_open));
1170  }
1171  if (rest.empty()) {
1172  return SymEngine::make_set_union(intervals);
1173  } else {
1174  return make_rcp<const Complement>(
1175  SymEngine::make_set_union(intervals), finiteset(rest));
1176  }
1177  }
1178 
1179  return SymEngine::set_complement_helper(rcp_from_this_cast<const Set>(), o);
1180 }
1181 
1182 RCP<const Set> FiniteSet::create(const set_basic &container) const
1183 {
1184  return finiteset(container);
1185 }
1186 
1187 Union::Union(const set_set &in)
1188  : container_(in){SYMENGINE_ASSIGN_TYPEID()
1189  SYMENGINE_ASSERT(Union::is_canonical(in))}
1190 
1191  hash_t Union::__hash__() const
1192 {
1193  hash_t seed = SYMENGINE_UNION;
1194  for (const auto &a : container_)
1195  hash_combine<Basic>(seed, *a);
1196  return seed;
1197 }
1198 
1199 bool Union::__eq__(const Basic &o) const
1200 {
1201  if (is_a<Union>(o)) {
1202  const Union &other = down_cast<const Union &>(o);
1203  return unified_eq(container_, other.container_);
1204  }
1205  return false;
1206 }
1207 
1208 bool Union::is_canonical(const set_set &in)
1209 {
1210  if (in.size() <= 1)
1211  return false;
1212  int count = 0;
1213  for (const auto &s : in) {
1214  if (is_a<FiniteSet>(*s)) {
1215  count++;
1216  }
1217  if (count >= 2)
1218  return false;
1219  }
1220  return true;
1221 }
1222 
1223 int Union::compare(const Basic &o) const
1224 {
1225  SYMENGINE_ASSERT(is_a<Union>(o))
1226  const Union &other = down_cast<const Union &>(o);
1227  return unified_compare(container_, other.container_);
1228 }
1229 
1230 RCP<const Set> Union::set_union(const RCP<const Set> &o) const
1231 {
1232  set_set container(container_);
1233  for (auto iter = container.begin(); iter != container.end(); ++iter) {
1234  auto temp = o->set_union(*iter);
1235  // If we are able to do union with `*iter`, we replace `*iter` with
1236  // the result of union.
1237  auto un = SymEngine::make_set_union({o, *iter});
1238  if (not eq(*temp, *un)) {
1239  iter = container.erase(iter);
1240  container.insert(temp);
1241  return SymEngine::set_union(container);
1242  }
1243  }
1244  container.insert(o);
1245  return SymEngine::make_set_union(container);
1246 }
1247 
1248 RCP<const Set> Union::set_intersection(const RCP<const Set> &o) const
1249 {
1250  set_set container;
1251  for (auto &a : container_) {
1252  container.insert(a->set_intersection(o));
1253  }
1254  return SymEngine::set_union(container);
1255 }
1256 
1257 RCP<const Set> Union::set_complement(const RCP<const Set> &o) const
1258 {
1259  set_set container;
1260  for (auto &a : container_) {
1261  container.insert(a->set_complement(o));
1262  }
1263  return SymEngine::set_intersection(container);
1264 }
1265 
1266 RCP<const Boolean> Union::contains(const RCP<const Basic> &o) const
1267 {
1268  bool has_contains = false;
1269  for (auto &a : container_) {
1270  auto contain = a->contains(o);
1271  if (eq(*contain, *boolTrue)) {
1272  return boolean(true);
1273  }
1274  if (is_a<Contains>(*contain)) {
1275  has_contains = true;
1276  }
1277  }
1278  if (has_contains) {
1279  return make_rcp<Contains>(o, rcp_from_this_cast<const Set>());
1280  }
1281  return boolean(false);
1282 }
1283 
1284 RCP<const Set> Union::create(const set_set &in) const
1285 {
1286  return SymEngine::set_union(in);
1287 }
1288 
1289 vec_basic Union::get_args() const
1290 {
1291  vec_basic v(container_.begin(), container_.end());
1292  return v;
1293 }
1294 
1295 Intersection::Intersection(const set_set &in)
1296  : container_(in){SYMENGINE_ASSIGN_TYPEID()
1297  SYMENGINE_ASSERT(Intersection::is_canonical(in))}
1298 
1299  hash_t Intersection::__hash__() const
1300 {
1301  hash_t seed = SYMENGINE_INTERSECTION;
1302  for (const auto &a : container_)
1303  hash_combine<Basic>(seed, *a);
1304  return seed;
1305 }
1306 
1307 bool Intersection::__eq__(const Basic &o) const
1308 {
1309  if (is_a<Intersection>(o)) {
1310  const Intersection &other = down_cast<const Intersection &>(o);
1311  return unified_eq(container_, other.container_);
1312  }
1313  return false;
1314 }
1315 
1316 bool Intersection::is_canonical(const set_set &in)
1317 {
1318  if (in.size() <= 1)
1319  return false;
1320  return true;
1321 }
1322 
1323 int Intersection::compare(const Basic &o) const
1324 {
1325  SYMENGINE_ASSERT(is_a<Intersection>(o))
1326  const Intersection &other = down_cast<const Intersection &>(o);
1327  return unified_compare(container_, other.container_);
1328 }
1329 
1330 RCP<const Set> Intersection::set_union(const RCP<const Set> &o) const
1331 {
1332  set_set container;
1333  for (auto &a : container_) {
1334  container.insert(a->set_union(o));
1335  }
1336  return SymEngine::set_intersection(container);
1337 }
1338 
1339 RCP<const Set> Intersection::set_intersection(const RCP<const Set> &o) const
1340 {
1341  set_set container(container_);
1342  for (auto iter = container.begin(); iter != container.end(); ++iter) {
1343  auto temp = o->set_intersection(*iter);
1344  // If we are able to do intersection with `*iter`, we replace `*iter`
1345  // with the result of intersection.
1346  auto un = SymEngine::make_set_intersection({o, *iter});
1347  if (not eq(*temp, *un)) {
1348  iter = container.erase(iter);
1349  container.insert(temp);
1350  return SymEngine::set_intersection(container);
1351  }
1352  }
1353  container.insert(o);
1354  return SymEngine::make_set_intersection(container);
1355 }
1356 
1357 RCP<const Set> Intersection::set_complement(const RCP<const Set> &o) const
1358 {
1359  set_set container;
1360  for (auto &a : container_) {
1361  container.insert(a->set_complement(o));
1362  }
1363  return SymEngine::set_intersection(container);
1364 }
1365 
1366 RCP<const Boolean> Intersection::contains(const RCP<const Basic> &o) const
1367 {
1368  bool has_contains = false;
1369  for (auto &a : container_) {
1370  auto contain = a->contains(o);
1371  if (is_a<Contains>(*contain)) {
1372  has_contains = true;
1373  } else if (eq(*contain, *boolFalse)) {
1374  return boolean(false);
1375  }
1376  }
1377  if (has_contains) {
1378  return make_rcp<Contains>(o, rcp_from_this_cast<const Set>());
1379  }
1380  return boolean(true);
1381 }
1382 
1383 RCP<const Set> Intersection::create(const set_set &in) const
1384 {
1385  return SymEngine::set_intersection(in);
1386 }
1387 
1388 vec_basic Intersection::get_args() const
1389 {
1390  vec_basic v(container_.begin(), container_.end());
1391  return v;
1392 }
1393 
1394 Complement::Complement(const RCP<const Set> &universe,
1395  const RCP<const Set> &container)
1396  : universe_(universe), container_(container){SYMENGINE_ASSIGN_TYPEID()}
1397 
1398  hash_t Complement::__hash__() const
1399 {
1400  hash_t seed = SYMENGINE_COMPLEMENT;
1401  hash_combine<Basic>(seed, *universe_);
1402  hash_combine<Basic>(seed, *container_);
1403  return seed;
1404 }
1405 
1406 bool Complement::__eq__(const Basic &o) const
1407 {
1408  if (is_a<Complement>(o)) {
1409  const Complement &other = down_cast<const Complement &>(o);
1410  return unified_eq(universe_, other.universe_)
1411  and unified_eq(container_, other.container_);
1412  }
1413  return false;
1414 }
1415 
1416 int Complement::compare(const Basic &o) const
1417 {
1418  SYMENGINE_ASSERT(is_a<Complement>(o))
1419  const Complement &other = down_cast<const Complement &>(o);
1420  int c1 = unified_compare(universe_, other.universe_);
1421  if (c1 != 0) {
1422  return c1;
1423  } else {
1424  return unified_compare(container_, other.container_);
1425  }
1426 }
1427 
1428 RCP<const Boolean> Complement::contains(const RCP<const Basic> &a) const
1429 {
1430  return logical_and(
1431  {universe_->contains(a), logical_not(container_->contains(a))});
1432 }
1433 
1434 RCP<const Set> Complement::set_union(const RCP<const Set> &o) const
1435 {
1436  // A' U C = (A n C')'
1437  RCP<const Set> ocomplement = o->set_complement(universe_);
1438  RCP<const Set> intersect
1439  = SymEngine::set_intersection({container_, ocomplement});
1440  return intersect->set_complement(universe_);
1441 }
1442 
1443 RCP<const Set> Complement::set_intersection(const RCP<const Set> &o) const
1444 {
1445  return SymEngine::set_intersection({rcp_from_this_cast<const Set>(), o});
1446 }
1447 
1448 RCP<const Set> Complement::set_complement(const RCP<const Set> &o) const
1449 {
1450  auto newuniv = SymEngine::set_union({o, universe_});
1451  return container_->set_complement(newuniv);
1452 }
1453 
1454 ConditionSet::ConditionSet(const RCP<const Basic> &sym,
1455  const RCP<const Boolean> &condition)
1456  : sym(sym), condition_(condition)
1457 {
1458  SYMENGINE_ASSIGN_TYPEID()
1459  SYMENGINE_ASSERT(ConditionSet::is_canonical(sym, condition))
1460 }
1461 
1462 bool ConditionSet::is_canonical(const RCP<const Basic> &sym,
1463  const RCP<const Boolean> &condition)
1464 {
1465  if (eq(*condition, *boolFalse) or eq(*condition, *boolTrue)
1466  or not is_a_Symbol(*sym)) {
1467  return false;
1468  } else if (is_a<Contains>(*condition)) {
1469  return false;
1470  }
1471  return true;
1472 }
1473 
1475 {
1476  hash_t seed = SYMENGINE_CONDITIONSET;
1477  hash_combine<Basic>(seed, *sym);
1478  hash_combine<Basic>(seed, *condition_);
1479  return seed;
1480 }
1481 
1482 bool ConditionSet::__eq__(const Basic &o) const
1483 {
1484  if (is_a<ConditionSet>(o)) {
1485  const ConditionSet &other = down_cast<const ConditionSet &>(o);
1486  return unified_eq(sym, other.get_symbol())
1487  and unified_eq(condition_, other.get_condition());
1488  }
1489  return false;
1490 }
1491 
1492 int ConditionSet::compare(const Basic &o) const
1493 {
1494  SYMENGINE_ASSERT(is_a<ConditionSet>(o))
1495  const ConditionSet &other = down_cast<const ConditionSet &>(o);
1496  int c1 = unified_compare(sym, other.get_symbol());
1497  if (c1 != 0) {
1498  return c1;
1499  } else {
1500  return unified_compare(condition_, other.get_condition());
1501  }
1502 }
1503 
1504 RCP<const Set> ConditionSet::set_union(const RCP<const Set> &o) const
1505 {
1506  return SymEngine::make_set_union({o, rcp_from_this_cast<const Set>()});
1507 }
1508 
1509 RCP<const Set> ConditionSet::set_intersection(const RCP<const Set> &o) const
1510 {
1511  if (not is_a<ConditionSet>(*o)) {
1512  return conditionset(sym, logical_and({condition_, o->contains(sym)}));
1513  }
1514  return make_set_intersection({rcp_from_this_cast<const Set>(), o});
1515 }
1516 
1517 RCP<const Set> ConditionSet::set_complement(const RCP<const Set> &o) const
1518 {
1519  return make_rcp<const Complement>(o, rcp_from_this_cast<const Set>());
1520 }
1521 
1522 RCP<const Boolean> ConditionSet::contains(const RCP<const Basic> &o) const
1523 {
1524  map_basic_basic d;
1525  d[sym] = o;
1526  auto cond = condition_->subs(d);
1527  if (not is_a_Boolean(*cond)) {
1528  throw SymEngineException("expected an object of type Boolean");
1529  }
1530  return rcp_static_cast<const Boolean>(cond);
1531 }
1532 
1533 ImageSet::ImageSet(const RCP<const Basic> &sym, const RCP<const Basic> &expr,
1534  const RCP<const Set> &base)
1535  : sym_(sym), expr_(expr), base_(base)
1536 {
1537  SYMENGINE_ASSIGN_TYPEID()
1538  SYMENGINE_ASSERT(ImageSet::is_canonical(sym, expr, base));
1539 }
1540 
1541 hash_t ImageSet::__hash__() const
1542 {
1543  hash_t seed = SYMENGINE_IMAGESET;
1544  hash_combine<Basic>(seed, *sym_);
1545  hash_combine<Basic>(seed, *expr_);
1546  hash_combine<Basic>(seed, *base_);
1547  return seed;
1548 }
1549 
1550 bool ImageSet::__eq__(const Basic &o) const
1551 {
1552  if (is_a<ImageSet>(o)) {
1553  const ImageSet &other = down_cast<const ImageSet &>(o);
1554  return unified_eq(sym_, other.sym_) and unified_eq(expr_, other.expr_)
1555  and unified_eq(base_, other.base_);
1556  }
1557  return false;
1558 }
1559 
1560 int ImageSet::compare(const Basic &o) const
1561 {
1562  SYMENGINE_ASSERT(is_a<ImageSet>(o))
1563  const ImageSet &other = down_cast<const ImageSet &>(o);
1564  int c1 = unified_compare(sym_, other.sym_);
1565  if (c1 != 0) {
1566  return c1;
1567  } else {
1568  int c2 = unified_compare(expr_, other.expr_);
1569  if (c2 != 0) {
1570  return c2;
1571  } else {
1572  return unified_compare(base_, other.base_);
1573  }
1574  }
1575 }
1576 
1577 bool ImageSet::is_canonical(const RCP<const Basic> &sym,
1578  const RCP<const Basic> &expr,
1579  const RCP<const Set> &base)
1580 {
1581  if (not is_a_Symbol(*sym) or eq(*expr, *sym) or is_a_Number(*expr)
1582  or eq(*base, *emptyset()))
1583  return false;
1584  return true;
1585 }
1586 
1587 RCP<const Boolean> ImageSet::contains(const RCP<const Basic> &a) const
1588 {
1589  throw SymEngineException("Not implemented");
1590 }
1591 
1592 RCP<const Set> ImageSet::set_union(const RCP<const Set> &o) const
1593 {
1594  return make_set_union({rcp_from_this_cast<const Set>(), o});
1595 }
1596 
1597 RCP<const Set> ImageSet::set_intersection(const RCP<const Set> &o) const
1598 {
1599  return SymEngine::set_intersection({rcp_from_this_cast<const Set>(), o});
1600 }
1601 
1602 RCP<const Set> ImageSet::set_complement(const RCP<const Set> &o) const
1603 {
1604  return SymEngine::set_complement(rcp_from_this_cast<const Set>(), o);
1605 }
1606 
1607 RCP<const Set> ImageSet::create(const RCP<const Basic> &sym,
1608  const RCP<const Basic> &expr,
1609  const RCP<const Set> &base) const
1610 {
1611  return imageset(sym, expr, base);
1612 }
1613 
1614 RCP<const Set> set_union(const set_set &in)
1615 {
1616  set_set input;
1617  set_basic combined_FiniteSet;
1618  for (auto it = in.begin(); it != in.end(); ++it) {
1619  if (is_a<FiniteSet>(**it)) {
1620  const FiniteSet &other = down_cast<const FiniteSet &>(**it);
1621  combined_FiniteSet.insert(other.get_container().begin(),
1622  other.get_container().end());
1623  } else if (is_a<UniversalSet>(**it)) {
1624  return universalset();
1625  } else if (not is_a<EmptySet>(**it)) {
1626  input.insert(*it);
1627  }
1628  }
1629  if (input.empty()) {
1630  return finiteset(combined_FiniteSet);
1631  } else if (input.size() == 1 && combined_FiniteSet.empty()) {
1632  return *input.begin();
1633  }
1634  // Now we rely on respective containers' own rules
1635  // TODO: Improve it to O(log n)
1636  RCP<const Set> combined_Rest = finiteset(combined_FiniteSet);
1637  for (auto it = input.begin(); it != input.end(); ++it) {
1638  combined_Rest = combined_Rest->set_union(*it);
1639  }
1640  return combined_Rest;
1641 }
1642 
1643 RCP<const Set> set_intersection(const set_set &in)
1644 {
1645  // https://en.wikipedia.org/wiki/Intersection_(set_theory)#Nullary_intersection
1646  if (in.empty())
1647  return universalset();
1648 
1649  // Global rules
1650  // If found any emptyset then return emptyset
1651  set_set incopy;
1652  for (const auto &input : in) {
1653  if (is_a<EmptySet>(*input)) {
1654  return emptyset();
1655  } else if (not is_a<UniversalSet>(*input)) {
1656  incopy.insert(input);
1657  }
1658  }
1659 
1660  if (incopy.empty())
1661  return universalset();
1662  if (incopy.size() == 1)
1663  return *incopy.begin();
1664 
1665  // Handle finite sets
1666  std::vector<RCP<const Set>> fsets, othersets;
1667  for (const auto &input : incopy) {
1668  if (is_a<FiniteSet>(*input)) {
1669  fsets.push_back(input);
1670  } else {
1671  othersets.push_back(input);
1672  }
1673  }
1674  if (fsets.size() != 0) {
1675  const FiniteSet &fs = down_cast<const FiniteSet &>(**fsets.begin());
1676  auto cont = fs.get_container();
1677  fsets.erase(fsets.begin());
1678  set_basic finalfs;
1679  for (const auto &fselement : cont) {
1680  bool present = true;
1681  for (const auto &fset : fsets) {
1682  auto contain = fset->contains(fselement);
1683  if (not(eq(*contain, *boolTrue) or eq(*contain, *boolFalse))) {
1684  return make_set_intersection(incopy);
1685  }
1686  present = present and eq(*contain, *boolTrue);
1687  }
1688  if (!present)
1689  continue;
1690  for (const auto &oset : othersets) {
1691  auto contain = oset->contains(fselement);
1692  if (not(eq(*contain, *boolTrue) or eq(*contain, *boolFalse))) {
1693  return make_set_intersection(incopy);
1694  }
1695  present = present and eq(*contain, *boolTrue);
1696  }
1697  if (present)
1698  finalfs.insert(fselement);
1699  }
1700  return finiteset(finalfs);
1701  }
1702 
1703  // If any of the sets is union, then return a Union of Intersections
1704  for (auto it = incopy.begin(); it != incopy.end(); ++it) {
1705  if (is_a<Union>(**it)) {
1706  auto container = down_cast<const Union &>(**it).get_container();
1707  incopy.erase(it);
1708  auto other = SymEngine::set_intersection(incopy);
1709  set_set usets;
1710  for (const auto &c : container) {
1711  usets.insert(SymEngine::set_intersection({c, other}));
1712  }
1713  return SymEngine::set_union(usets);
1714  }
1715  }
1716 
1717  // Simplify and return a `Complement` if any of the sets is a complement
1718  for (auto it = incopy.begin(); it != incopy.end(); ++it) {
1719  if (is_a<Complement>(**it)) {
1720  auto container
1721  = down_cast<const Complement &>(**it).get_container();
1722  auto universe = down_cast<const Complement &>(**it).get_universe();
1723  incopy.erase(it);
1724  incopy.insert(universe);
1725  auto other = SymEngine::set_intersection(incopy);
1726  return SymEngine::set_complement(other, container);
1727  }
1728  }
1729 
1730  // Pair-wise rules
1731  // TO-DO: needs the following improvement once Intersection
1732  // class is implemented.
1733  // input_oset if found to be not simplified, then skip this
1734  // pair.
1735  if (incopy.size() > 1) {
1736  auto temp = *incopy.begin();
1737  auto it = std::next(incopy.begin());
1738  for (; it != incopy.end(); ++it) {
1739  temp = temp->set_intersection(*it);
1740  }
1741  return temp;
1742  }
1743 
1744  return make_set_intersection(incopy);
1745 }
1746 
1747 // helper to avoid redundant code
1748 RCP<const Set> set_complement_helper(const RCP<const Set> &container,
1749  const RCP<const Set> &universe)
1750 {
1751  if (is_a<Union>(*universe)) {
1752  auto univ = down_cast<const Union &>(*universe).get_container();
1753  set_set container_;
1754  for (auto &a : univ) {
1755  container_.insert(container->set_complement(a));
1756  }
1757  return SymEngine::set_union(container_);
1758  } else if (is_a<EmptySet>(*universe)) {
1759  return emptyset();
1760  } else if (is_a<FiniteSet>(*universe)) {
1761  const FiniteSet &other = down_cast<const FiniteSet &>(*universe);
1762  set_basic container_;
1763  set_basic rest;
1764  for (const auto &a : other.get_container()) {
1765  auto contain = container->contains(a);
1766  if (eq(*contain, *boolFalse)) {
1767  container_.insert(a);
1768  } else if (is_a<Contains>(*contain)) {
1769  rest.insert(a);
1770  }
1771  }
1772  if (rest.empty()) {
1773  return finiteset(container_);
1774  } else {
1775  return SymEngine::set_union(
1776  {finiteset(container_),
1777  make_rcp<const Complement>(finiteset(rest), container)});
1778  }
1779  }
1780  return make_rcp<const Complement>(universe, container);
1781 }
1782 
1783 RCP<const Set> set_complement(const RCP<const Set> &universe,
1784  const RCP<const Set> &container)
1785 {
1786  // represents universe - container
1787  return container->set_complement(universe);
1788 }
1789 
1790 RCP<const Set> conditionset(const RCP<const Basic> &sym,
1791  const RCP<const Boolean> &condition)
1792 {
1793  if (eq(*condition, *boolean(false))) {
1794  return emptyset();
1795  } else if (eq(*condition, *boolean(true))) {
1796  return universalset();
1797  }
1798  if (is_a<And>(*condition)) {
1799  auto cont = down_cast<const And &>(*condition).get_container();
1800  set_boolean newcont;
1801  set_basic present, others;
1802  for (auto it = cont.begin(); it != cont.end(); it++) {
1803  if (is_a<Contains>(**it)
1804  and eq(*down_cast<const Contains &>(**it).get_expr(), *sym)
1805  and is_a<FiniteSet>(
1806  *down_cast<const Contains &>(**it).get_set())) {
1807  auto fset = down_cast<const Contains &>(**it).get_set();
1808  auto fcont
1809  = down_cast<const FiniteSet &>(*fset).get_container();
1810  // use the result of simplification done in `logical_and()`
1811  for (const auto &elem : fcont) {
1812  if (not(is_a_Number(*elem) or is_a<Constant>(*elem))) {
1813  others.insert(elem);
1814  } else {
1815  // logical_and() doesn't guarantee that if element of a
1816  // finiteset is a number, then it satisfies other
1817  // conditions
1818  // it only assures that there doesn't exist any such
1819  // element of finiteset that surely fails in other
1820  // conditions.
1821  auto restCont = cont;
1822  restCont.erase(*it);
1823  auto restCond = logical_and(restCont);
1824  map_basic_basic d;
1825  d[sym] = elem;
1826  auto contain = restCond->subs(d);
1827  if (eq(*contain, *boolean(true))) {
1828  present.insert(elem);
1829  } else if (not eq(*contain, *boolean(false))) {
1830  others.insert(elem);
1831  } else {
1832  throw SymEngineException("element should have "
1833  "been removed within "
1834  "logical_and()");
1835  }
1836  }
1837  }
1838  } else {
1839  newcont.insert(*it);
1840  }
1841  }
1842  if (not present.empty()) {
1843  newcont.insert(finiteset(others)->contains(sym));
1844  return SymEngine::set_union(
1845  {finiteset(present), conditionset(sym, logical_and(newcont))});
1846  }
1847  }
1848  if (is_a<Contains>(*condition)) {
1849  return down_cast<const Contains &>(*condition).get_set();
1850  }
1851  return make_rcp<const ConditionSet>(sym, condition);
1852 }
1853 
1854 } // namespace SymEngine
Classes and functions relating to the binary operation of addition.
SYMENGINE_EXPORT 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:97
Basic()
Constructor.
Definition: basic.h:120
int compare(const Basic &o) const override
Definition: sets.cpp:1416
bool __eq__(const Basic &o) const override
Test equality.
Definition: sets.cpp:1406
hash_t __hash__() const override
Definition: sets.cpp:1398
int compare(const Basic &o) const override
Definition: sets.cpp:1492
bool __eq__(const Basic &o) const override
Test equality.
Definition: sets.cpp:1482
hash_t __hash__() const override
Definition: sets.cpp:1474
bool __eq__(const Basic &o) const override
Test equality.
Definition: sets.cpp:869
int compare(const Basic &o) const override
Definition: sets.cpp:878
hash_t __hash__() const override
Definition: sets.cpp:861
bool __eq__(const Basic &o) const override
Test equality.
Definition: sets.cpp:1550
int compare(const Basic &o) const override
Definition: sets.cpp:1560
bool __eq__(const Basic &o) const override
Test equality.
Definition: sets.cpp:1307
vec_basic get_args() const override
Returns the list of arguments.
Definition: sets.cpp:1388
int compare(const Basic &o) const override
Definition: sets.cpp:1323
hash_t __hash__() const override
Definition: sets.cpp:1191
int compare(const Basic &o) const override
Definition: sets.cpp:1223
vec_basic get_args() const override
Returns the list of arguments.
Definition: sets.cpp:1289
bool __eq__(const Basic &o) const override
Test equality.
Definition: sets.cpp:1199
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:611
RCP< const Complexes > complexes()
Definition: sets.h:554
std::enable_if< std::is_integral< T >::value, RCP< const Integer > >::type integer(T i)
Definition: integer.h:197
RCP< const Reals > reals()
Definition: sets.h:560
RCP< const Naturals > naturals()
Definition: sets.h:578
RCP< const EmptySet > emptyset()
Definition: sets.h:590
RCP< const Integers > integers()
Definition: sets.h:572
RCP< const Boolean > Ge(const RCP< const Basic > &lhs, const RCP< const Basic > &rhs)
Convenience function returning LessThan object.
Definition: logic.cpp:733
RCP< const Basic > max(const vec_basic &arg)
Canonicalize Max:
Definition: functions.cpp:3553
RCP< const Basic > ceiling(const RCP< const Basic > &arg)
Canonicalize Ceiling:
Definition: functions.cpp:712
RCP< const Boolean > Eq(const RCP< const Basic > &lhs)
Returns the canonicalized Equality object from a single argument.
Definition: logic.cpp:642
RCP< const UniversalSet > universalset()
Definition: sets.h:596
RCP< const Basic > floor(const RCP< const Basic > &arg)
Canonicalize Floor:
Definition: functions.cpp:618
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
Definition: basic-inl.h:21
bool neq(const Basic &a, const Basic &b)
Checks inequality for a and b
Definition: basic-inl.h:29
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
RCP< const Naturals0 > naturals0()
Definition: sets.h:584
RCP< const Basic > min(const vec_basic &arg)
Canonicalize Min:
Definition: functions.cpp:3657
RCP< const Rationals > rationals()
Definition: sets.h:566
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 Set > conditionset(const RCP< const Basic > &sym, const RCP< const Boolean > &condition)
Definition: sets.cpp:1790