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