1
2
3
4
5 package main
6
7 import (
8 "fmt"
9 "simd/archsimd/_gen/specgen"
10 "slices"
11 )
12
13
14 type result struct{ n, d int }
15
16 func (r result) miss() int { return r.d - r.n }
17
18
19
20
21 type tally[K comparable] struct {
22 all map[K]bool
23 hit map[K]bool
24 }
25
26 func (t *tally[K]) add(k K, done bool) {
27 if t.all == nil {
28 t.all, t.hit = map[K]bool{}, map[K]bool{}
29 }
30 t.all[k] = true
31 if done {
32 t.hit[k] = true
33 }
34 }
35
36 func (t *tally[K]) result() result { return result{len(t.hit), len(t.all)} }
37
38
39 func (t *tally[K]) has(k K) bool { return t.all[k] }
40 func (t *tally[K]) done(k K) bool { return t.hit[k] }
41
42
43
44 func (t *tally[K]) missed() []string {
45 var out []string
46 for k := range t.all {
47 if !t.hit[k] {
48 out = append(out, fmt.Sprint(k))
49 }
50 }
51 slices.Sort(out)
52 return out
53 }
54
55
56
57 type pivot[K comparable] struct {
58 by map[string]*tally[K]
59 }
60
61 func (p *pivot[K]) add(dim string, k K, done bool) {
62 if p.by == nil {
63 p.by = map[string]*tally[K]{}
64 }
65 t := p.by[dim]
66 if t == nil {
67 t = new(tally[K])
68 p.by[dim] = t
69 }
70 t.add(k, done)
71 }
72
73
74
75 func (p *pivot[K]) fold(from, to string) {
76 src := p.by[from]
77 for k := range src.all {
78 p.add(to, k, src.done(k))
79 }
80 }
81
82 func (p *pivot[K]) dims() []string { return sortedKeys(p.by) }
83
84 func (p *pivot[K]) result(dim string) result {
85 if t := p.by[dim]; t != nil {
86 return t.result()
87 }
88 return result{}
89 }
90
91
92
93 func tallyBy[K comparable](facts []fact, key func(fact) K, done func(fact) bool) *tally[K] {
94 t := new(tally[K])
95 for _, f := range facts {
96 t.add(key(f), done(f))
97 }
98 return t
99 }
100
101
102 func pivotBy[K comparable](facts []fact, dim func(fact) string, key func(fact) K, done func(fact) bool) *pivot[K] {
103 p := new(pivot[K])
104 for _, f := range facts {
105 p.add(dim(f), key(f), done(f))
106 }
107 return p
108 }
109
110
111
112 func countBy[K comparable](facts []fact, key func(fact) K) int {
113 seen := map[K]bool{}
114 for _, f := range facts {
115 seen[key(f)] = true
116 }
117 return len(seen)
118 }
119
120 func groupBy[T any, K comparable](s []T, key func(T) K) map[K][]T {
121 m := map[K][]T{}
122 for _, v := range s {
123 m[key(v)] = append(m[key(v)], v)
124 }
125 return m
126 }
127
128 func sortedKeys[V any](m map[string]V) []string {
129 ks := make([]string, 0, len(m))
130 for k := range m {
131 ks = append(ks, k)
132 }
133 slices.Sort(ks)
134 return ks
135 }
136
137
138
139 func equalBy(a, b []param, f func(param) string) bool {
140 if len(a) != len(b) {
141 return false
142 }
143 for i := range a {
144 if f(a[i]) != f(b[i]) {
145 return false
146 }
147 }
148 return true
149 }
150
151 func paramType(p param) string { return p.typ }
152
153
154
155 func specParams(as []specgen.Arg) []param {
156 ps := make([]param, len(as))
157 for i, a := range as {
158 ps[i] = param{a.Name, a.Type.String()}
159 }
160 return ps
161 }
162
163
164
165 func named(p param) bool { return p.name != "" && p.name != "_" }
166
167
168
169
170 func namesClash(api, spec []param) bool {
171 if len(api) != len(spec) {
172 return false
173 }
174 for i := range api {
175 if named(api[i]) && named(spec[i]) && api[i].name != spec[i].name {
176 return true
177 }
178 }
179 return false
180 }
181
182
183
184 func namesMissing(api, spec []param) bool {
185 if len(api) != len(spec) {
186 return false
187 }
188 for i := range api {
189 if named(spec[i]) && !named(api[i]) {
190 return true
191 }
192 }
193 return false
194 }
195
196
197
198 func namesConsistent(lists [][]param) bool {
199 for _, l := range lists[1:] {
200 if len(l) != len(lists[0]) {
201 return false
202 }
203 }
204 for i := range lists[0] {
205 var name string
206 for _, l := range lists {
207 if !named(l[i]) {
208 continue
209 }
210 if name == "" {
211 name = l[i].name
212 } else if l[i].name != name {
213 return false
214 }
215 }
216 }
217 return true
218 }
219
View as plain text