-
Notifications
You must be signed in to change notification settings - Fork 475
/
set_utils.go
87 lines (73 loc) · 2.03 KB
/
set_utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package selector
import (
"math"
"strconv"
"strings"
)
// PowerSet implements a range-able combination generator. It takes a set, and
// returns a channel over which all possible combinations of selectors are eventually
// returned. It is meant to aid in the discovery of applicable cache entries, given the
// superset of selectors discovered during attestation.
func PowerSet(selectors *set) <-chan Set {
c := make(chan Set)
go func() {
powerSet(selectors, c)
close(c)
}()
return c
}
// EqualSet determines whether two sets of selectors are equal or not
func EqualSet(a, b *set) bool {
if a.Size() != b.Size() {
return false
}
return IncludesSet(a, b)
}
// Includes determines whether a given selector is present in a set
func Includes(set *set, item *Selector) bool {
in, ok := (*set)[*item]
return ok && (*item) == (*in)
}
// IncludesSet returns true if s2 is included in s1. This is, all the s2 selectors
// are also present in s1.
func IncludesSet(s1, s2 *set) bool {
// If s2 has more elements than s1, it cannot be included.
if len(*s2) > len(*s1) {
return false
}
for key2, sel2 := range *s2 {
if sel1, found := (*s1)[key2]; found {
if *sel2 != *sel1 {
return false
}
} else {
return false
}
}
return true
}
// powerSet, given a set of selectors, returns every possible combination
// of selector subsets.
//
// https://en.wikipedia.org/wiki/Power_set
func powerSet(s *set, c chan Set) {
sarr := s.Array()
powSetSize := math.Pow(2, float64(len(*s)))
// Skip the empty set by starting the counter at 1
for i := 1; i < int(powSetSize); i++ {
set := &set{}
// Form binary representation of the counter
binaryString := strconv.FormatUint(uint64(i), 2)
binary := strings.Split(binaryString, "")
// Walk through the binary, and append
// "enabled" elements to the working set
for position := 0; position < len(binary); position++ {
// Read the binary right to left
negPosition := (len(binary) - position - 1)
if binary[negPosition] == "1" {
set.Add(sarr[position])
}
}
c <- set
}
}