package sets // Union returns a union of the given sets (left ∪ right). func Union[T comparable](left, right *Set[T]) *Set[T] { left.mux.RLock() right.mux.RLock() defer left.mux.RUnlock() defer right.mux.RUnlock() store := map[T]struct{}{} for k := range left.store { store[k] = struct{}{} } for k := range right.store { if _, ok := store[k]; !ok { store[k] = struct{}{} } } return &Set[T]{ store: store, } } // Intersection returns an intersection of the given sets (left ∩ right). func Intersection[T comparable](left, right *Set[T]) *Set[T] { left.mux.RLock() right.mux.RLock() defer left.mux.RUnlock() defer right.mux.RUnlock() store := map[T]struct{}{} for lk := range left.store { if _, ok := right.store[lk]; ok { store[lk] = struct{}{} } } return &Set[T]{ store: store, } } // Diff returns the relative complement of sets (left ∖ right). func Diff[T comparable](left, right *Set[T]) *Set[T] { left.mux.RLock() right.mux.RLock() defer left.mux.RUnlock() defer right.mux.RUnlock() store := map[T]struct{}{} for lk := range left.store { if _, ok := right.store[lk]; !ok { store[lk] = struct{}{} } } return &Set[T]{ store: store, } } // SymmetricDiff returns the symmetric difference between sets (left ⊖ right). func SymmetricDiff[T comparable](left, right *Set[T]) *Set[T] { left.mux.RLock() right.mux.RLock() defer left.mux.RUnlock() defer right.mux.RUnlock() store := map[T]struct{}{} for lk := range left.store { if _, ok := right.store[lk]; !ok { store[lk] = struct{}{} } } for rk := range right.store { if _, ok := left.store[rk]; !ok { store[rk] = struct{}{} } } return &Set[T]{ store: store, } } // Equal checks whether the sets are equal (left = right). func Equal[T comparable](left, right *Set[T]) bool { left.mux.RLock() right.mux.RLock() defer left.mux.RUnlock() defer right.mux.RUnlock() if len(left.store) != len(right.store) { return false } for lk := range left.store { if _, ok := right.store[lk]; !ok { return false } } return true }