10b57cec5SDimitry Andric //===-- llvm/ADT/SetOperations.h - Generic Set Operations -------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
81fd87a68SDimitry Andric ///
91fd87a68SDimitry Andric /// \file
101fd87a68SDimitry Andric /// This file defines generic set operations that may be used on set's of
111fd87a68SDimitry Andric /// different types, and different element types.
121fd87a68SDimitry Andric ///
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #ifndef LLVM_ADT_SETOPERATIONS_H
160b57cec5SDimitry Andric #define LLVM_ADT_SETOPERATIONS_H
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric namespace llvm {
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric /// set_union(A, B) - Compute A := A u B, return whether A changed.
210b57cec5SDimitry Andric ///
220b57cec5SDimitry Andric template <class S1Ty, class S2Ty>
set_union(S1Ty & S1,const S2Ty & S2)230b57cec5SDimitry Andric bool set_union(S1Ty &S1, const S2Ty &S2) {
240b57cec5SDimitry Andric   bool Changed = false;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric   for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end();
270b57cec5SDimitry Andric        SI != SE; ++SI)
280b57cec5SDimitry Andric     if (S1.insert(*SI).second)
290b57cec5SDimitry Andric       Changed = true;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric   return Changed;
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric /// set_intersect(A, B) - Compute A := A ^ B
350b57cec5SDimitry Andric /// Identical to set_intersection, except that it works on set<>'s and
360b57cec5SDimitry Andric /// is nicer to use.  Functionally, this iterates through S1, removing
370b57cec5SDimitry Andric /// elements that are not contained in S2.
380b57cec5SDimitry Andric ///
390b57cec5SDimitry Andric template <class S1Ty, class S2Ty>
set_intersect(S1Ty & S1,const S2Ty & S2)400b57cec5SDimitry Andric void set_intersect(S1Ty &S1, const S2Ty &S2) {
410b57cec5SDimitry Andric    for (typename S1Ty::iterator I = S1.begin(); I != S1.end();) {
420b57cec5SDimitry Andric      const auto &E = *I;
430b57cec5SDimitry Andric      ++I;
440b57cec5SDimitry Andric      if (!S2.count(E)) S1.erase(E);   // Erase element if not in S2
450b57cec5SDimitry Andric    }
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric 
4806c3fb27SDimitry Andric template <class S1Ty, class S2Ty>
set_intersection_impl(const S1Ty & S1,const S2Ty & S2)4906c3fb27SDimitry Andric S1Ty set_intersection_impl(const S1Ty &S1, const S2Ty &S2) {
5006c3fb27SDimitry Andric    S1Ty Result;
5106c3fb27SDimitry Andric    for (typename S1Ty::const_iterator SI = S1.begin(), SE = S1.end(); SI != SE;
5206c3fb27SDimitry Andric         ++SI)
5306c3fb27SDimitry Andric      if (S2.count(*SI))
5406c3fb27SDimitry Andric       Result.insert(*SI);
5506c3fb27SDimitry Andric    return Result;
5606c3fb27SDimitry Andric }
5706c3fb27SDimitry Andric 
5806c3fb27SDimitry Andric /// set_intersection(A, B) - Return A ^ B
5906c3fb27SDimitry Andric template <class S1Ty, class S2Ty>
set_intersection(const S1Ty & S1,const S2Ty & S2)6006c3fb27SDimitry Andric S1Ty set_intersection(const S1Ty &S1, const S2Ty &S2) {
6106c3fb27SDimitry Andric    if (S1.size() < S2.size())
6206c3fb27SDimitry Andric      return set_intersection_impl(S1, S2);
6306c3fb27SDimitry Andric    else
6406c3fb27SDimitry Andric      return set_intersection_impl(S2, S1);
6506c3fb27SDimitry Andric }
6606c3fb27SDimitry Andric 
670b57cec5SDimitry Andric /// set_difference(A, B) - Return A - B
680b57cec5SDimitry Andric ///
690b57cec5SDimitry Andric template <class S1Ty, class S2Ty>
set_difference(const S1Ty & S1,const S2Ty & S2)700b57cec5SDimitry Andric S1Ty set_difference(const S1Ty &S1, const S2Ty &S2) {
710b57cec5SDimitry Andric   S1Ty Result;
720b57cec5SDimitry Andric   for (typename S1Ty::const_iterator SI = S1.begin(), SE = S1.end();
730b57cec5SDimitry Andric        SI != SE; ++SI)
740b57cec5SDimitry Andric     if (!S2.count(*SI))       // if the element is not in set2
750b57cec5SDimitry Andric       Result.insert(*SI);
760b57cec5SDimitry Andric   return Result;
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric /// set_subtract(A, B) - Compute A := A - B
800b57cec5SDimitry Andric ///
810b57cec5SDimitry Andric template <class S1Ty, class S2Ty>
set_subtract(S1Ty & S1,const S2Ty & S2)820b57cec5SDimitry Andric void set_subtract(S1Ty &S1, const S2Ty &S2) {
830b57cec5SDimitry Andric   for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end();
840b57cec5SDimitry Andric        SI != SE; ++SI)
850b57cec5SDimitry Andric     S1.erase(*SI);
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric 
8806c3fb27SDimitry Andric /// set_subtract(A, B, C, D) - Compute A := A - B, set C to the elements of B
8906c3fb27SDimitry Andric /// removed from A (A ^ B), and D to the elements of B not found in and removed
9006c3fb27SDimitry Andric /// from A (B - A).
9106c3fb27SDimitry Andric template <class S1Ty, class S2Ty>
set_subtract(S1Ty & S1,const S2Ty & S2,S1Ty & Removed,S1Ty & Remaining)9206c3fb27SDimitry Andric void set_subtract(S1Ty &S1, const S2Ty &S2, S1Ty &Removed, S1Ty &Remaining) {
9306c3fb27SDimitry Andric   for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end(); SI != SE;
9406c3fb27SDimitry Andric        ++SI)
9506c3fb27SDimitry Andric     if (S1.erase(*SI))
9606c3fb27SDimitry Andric       Removed.insert(*SI);
9706c3fb27SDimitry Andric     else
9806c3fb27SDimitry Andric       Remaining.insert(*SI);
9906c3fb27SDimitry Andric }
10006c3fb27SDimitry Andric 
1015ffd83dbSDimitry Andric /// set_is_subset(A, B) - Return true iff A in B
1025ffd83dbSDimitry Andric ///
1035ffd83dbSDimitry Andric template <class S1Ty, class S2Ty>
set_is_subset(const S1Ty & S1,const S2Ty & S2)1045ffd83dbSDimitry Andric bool set_is_subset(const S1Ty &S1, const S2Ty &S2) {
1055ffd83dbSDimitry Andric   if (S1.size() > S2.size())
1065ffd83dbSDimitry Andric     return false;
107fe6060f1SDimitry Andric   for (const auto It : S1)
1085ffd83dbSDimitry Andric     if (!S2.count(It))
1095ffd83dbSDimitry Andric       return false;
1105ffd83dbSDimitry Andric   return true;
1115ffd83dbSDimitry Andric }
1125ffd83dbSDimitry Andric 
1130b57cec5SDimitry Andric } // End llvm namespace
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric #endif
116