File Coverage

keyval.h
Criterion Covered Total %
statement 122 142 85.9
branch 65 88 73.8
condition n/a
subroutine n/a
pod n/a
total 187 230 81.3


line stmt bran cond sub pod time code
1             #ifndef MPU_KEYVAL_H
2             #define MPU_KEYVAL_H
3              
4             #include "ptypes.h"
5              
6             typedef struct {
7             UV key;
8             UV val;
9             } keyval_t;
10              
11             typedef struct {
12             keyval_t *keyval;
13             UV mask;
14             long maxsize;
15             long size;
16             } set_t;
17              
18              
19              
20              
21             #if BITS_PER_WORD == 32
22             static UV _hash(UV x) {
23             x = ((x >> 16) ^ x) * 0x45d9f3b;
24             x = ((x >> 16) ^ x) * 0x45d9f3b;
25             x = (x >> 16) ^ x;
26             return x;
27             }
28             #else
29 8731           static UV _hash(UV x) {
30 8731           x = (x ^ (x >> 30)) * UVCONST(0xbf58476d1ce4e5b9);
31 8731           x = (x ^ (x >> 27)) * UVCONST(0x94d049bb133111eb);
32 8731           x = x ^ (x >> 31);
33 8731           return x;
34             }
35             #endif
36              
37              
38             /******************************************************************************/
39              
40 284           static void init_set(set_t *S, UV isize) {
41 284           int bits = 0;
42 1397 100         while (isize > 0) {
43 1113           bits++;
44 1113           isize >>= 1;
45             }
46 284           S->size = 0;
47 284           S->maxsize = UVCONST(1) << ((bits < 3) ? 3 : bits);
48 284           S->mask = S->maxsize - 1;
49 284 50         Newz(0,S->keyval,S->maxsize,keyval_t);
50 284           }
51              
52 284           static void free_set(set_t *S) {
53 284           S->size = S->maxsize = 0;
54 284           Safefree(S->keyval);
55 284           }
56              
57 10           static void _set_expand(set_t *S) {
58 10           long i, max = S->maxsize, newmax = max*2, newsize = 0, newmask = newmax-1;
59             keyval_t *nkv;
60 10 50         Newz(0, nkv, newmax, keyval_t);
61 146 100         for (i = 0; i < max; i++) {
62 136           UV key = S->keyval[i].key;
63 136 100         if (key != 0) {
64 105           UV h = _hash(key) & newmask;
65 131 100         while (nkv[h].key > 0 && nkv[h].key != key)
    50          
66 26           h = (h+1) & newmask;
67 105           nkv[h] = S->keyval[i];
68 105           newsize++;
69             }
70             }
71 10           Safefree(S->keyval);
72 10           S->keyval = nkv;
73 10           S->maxsize = newmax;
74 10           S->mask = newmax-1;
75 10 50         MPUassert(newsize == S->size, "keyval set size mismatch");
76 10           }
77              
78 4117           static long set_search(set_t S, UV key) {
79 4117           long h = _hash(key) & S.mask;
80 4469 100         while (S.keyval[h].key > 0 && S.keyval[h].key != key)
    100          
81 352           h = (h+1) & S.mask; /* Linear probe */
82 4117 100         return (S.keyval[h].key == key) ? h : -1;
83             }
84              
85 4117           static UV set_getval(set_t S, UV key) {
86 4117           long i = set_search(S, key);
87 4117 100         return (i == -1) ? 0 : S.keyval[i].val;
88             }
89              
90 3909           static void set_addsum(set_t *S, keyval_t kv) {
91 3909           UV h = _hash(kv.key) & S->mask;
92 4819 100         while (S->keyval[h].key > 0 && S->keyval[h].key != kv.key)
    100          
93 910           h = (h+1) & S->mask;
94 3909 100         if (S->keyval[h].key == kv.key) {
95             /* if (kv.val > UV_MAX - S->keyval[h].val) croak("add overflow\n"); */
96 1611           S->keyval[h].val += kv.val;
97             } else {
98 2298           S->keyval[h] = kv;
99 2298 100         if (S->size++ > 0.65 * S->maxsize)
100 10           _set_expand(S);
101             }
102 3909           }
103              
104 245           static void set_merge(set_t *S, set_t T) {
105             long j;
106 10013 100         for (j = 0; j < T.maxsize; j++)
107 9768 100         if (T.keyval[j].key > 0)
108 1935           set_addsum(S, T.keyval[j]);
109 245           }
110              
111             /******************************************************************************/
112              
113             typedef struct {
114             UV key;
115             UV *vals;
116             long size;
117             long maxsize;
118             } keylist_t;
119              
120             typedef struct {
121             keylist_t *keylist;
122             UV mask;
123             long maxsize;
124             long size;
125             } set_list_t;
126              
127 25           static void init_setlist(set_list_t *L, UV isize) {
128 25           int bits = 0;
129 144 100         while (isize > 0) {
130 119           bits++;
131 119           isize >>= 1;
132             }
133 25           L->size = 0;
134 25           L->maxsize = UVCONST(1) << ((bits < 3) ? 3 : bits);
135 25           L->mask = L->maxsize - 1;
136 25 50         Newz(0, L->keylist, L->maxsize, keylist_t);
137 25           }
138              
139 25           static void free_setlist(set_list_t *L) {
140             long i;
141 25           L->size = L->maxsize = 0;
142 25 50         for (i = 0; i < L->maxsize; i++)
143 0 0         if (L->keylist[i].size > 0)
144 0           Safefree(L->keylist[i].vals);
145 25           Safefree(L->keylist);
146 25           }
147              
148 0           static void _setlist_expand(set_list_t *L) {
149 0           long i, max = L->maxsize, newmax = max*2, newsize = 0, newmask = newmax-1;
150             keylist_t *nlist;
151 0 0         Newz(0, nlist, newmax, keylist_t);
152 0 0         for (i = 0; i < max; i++) {
153 0           UV key = L->keylist[i].key;
154 0 0         if (key != 0) {
155 0           UV h = _hash(key) & newmask;
156 0 0         while (nlist[h].key > 0 && nlist[h].key != key)
    0          
157 0           h = (h+1) & newmask;
158 0           nlist[h] = L->keylist[i];
159 0           newsize++;
160             }
161             }
162 0           Safefree(L->keylist);
163 0           L->keylist = nlist;
164 0           L->maxsize = newmax;
165 0           L->mask = newmax-1;
166 0 0         MPUassert(newsize == L->size, "setlist size mismatch");
167 0           }
168              
169 408           static long setlist_search(set_list_t L, UV key) {
170 408           long h = _hash(key) & L.mask;
171 420 100         while (L.keylist[h].key > 0 && L.keylist[h].key != key)
    100          
172 12           h = (h+1) & L.mask; /* Linear probe */
173 408 100         return (L.keylist[h].key == key) ? h : -1;
174             }
175              
176 192           static void setlist_addlist(set_list_t *L, UV key, long nvals, UV* list, UV mult) {
177             UV *vptr;
178 192           long j, h = _hash(key) & L->mask;
179 206 100         while (L->keylist[h].key > 0 && L->keylist[h].key != key)
    100          
180 14           h = (h+1) & L->mask;
181 192 100         if (L->keylist[h].key == key) {
182 56           long size = L->keylist[h].size;
183 56           long maxsize = L->keylist[h].maxsize;
184 56 100         if (size + nvals > maxsize) {
185 3           maxsize = 2 * (size+nvals);
186 3 50         Renew(L->keylist[h].vals, maxsize, UV);
187 3           L->keylist[h].maxsize = maxsize;
188             }
189 56           vptr = L->keylist[h].vals + size;
190 196 100         for (j = 0; j < nvals; j++)
191 140           vptr[j] = list[j] * mult;
192 56           L->keylist[h].size = size + nvals;
193             } else {
194 136 100         long maxsize = (nvals < 5) ? 12 : (nvals+1) * 2;
195 136 50         New(0, L->keylist[h].vals, maxsize, UV);
196 136           L->keylist[h].maxsize = maxsize;
197 136           vptr = L->keylist[h].vals;
198 478 100         for (j = 0; j < nvals; j++)
199 342           vptr[j] = list[j] * mult;
200 136           L->keylist[h].size = nvals;
201 136           L->keylist[h].key = key;
202 136 50         if (L->size++ > 0.65 * L->maxsize)
203 0           _setlist_expand(L);
204             }
205 192           }
206              
207 4           static void setlist_addval(set_list_t *L, UV key, UV val) {
208 4           setlist_addlist(L, key, 1, &val, 1);
209 4           }
210              
211 408           static UV* setlist_getlist(UV *nvals, set_list_t L, UV key) {
212 408           long i = setlist_search(L, key);
213 408 100         if (i == -1) {
214 313           *nvals = 0;
215 313           return 0;
216             }
217 95           *nvals = L.keylist[i].size;
218 95           return L.keylist[i].vals;
219             }
220              
221 23           static void setlist_merge(set_list_t *L, set_list_t T) {
222             long j;
223 615 100         for (j = 0; j < T.maxsize; j++) {
224 592 100         if (T.keylist[j].key > 0) {
225 95           UV key = T.keylist[j].key;
226 95           UV nvals = T.keylist[j].size;
227 95           UV *vals = T.keylist[j].vals;
228 95           setlist_addlist(L, key, nvals, vals, 1);
229             }
230             }
231 23           }
232              
233             #endif