| File: | src/table.c |
| Warning: | line 283, column 18 Division by zero |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /***************************************************************************** | |||
| 2 | * | |||
| 3 | * table.c: Hash table data type. | |||
| 4 | * | |||
| 5 | * Copyright (c) 1990-2007 Aldor Software Organization Ltd (Aldor.org). | |||
| 6 | * | |||
| 7 | ****************************************************************************/ | |||
| 8 | ||||
| 9 | #include "axlgen.h" | |||
| 10 | #include "format.h" | |||
| 11 | #include "store.h" | |||
| 12 | #include "table.h" | |||
| 13 | #include "util.h" | |||
| 14 | ||||
| 15 | # define TBL_InitBuckC7 7 /* Largest prime under 2**i, for some i. */ | |||
| 16 | # define TBL_MaxLoad5 5 | |||
| 17 | ||||
| 18 | localstatic Table tblNew0 (TblHashFun, TblEqFun, int buckc); | |||
| 19 | localstatic void tblEnlarge (Table); | |||
| 20 | ||||
| 21 | Table | |||
| 22 | tblNew(TblHashFun hash, TblEqFun eq) | |||
| 23 | { | |||
| 24 | return tblNew0(hash, eq, TBL_InitBuckC7); | |||
| 25 | } | |||
| 26 | ||||
| 27 | localstatic Table | |||
| 28 | tblNew0(TblHashFun hash, TblEqFun eq, int buckc) | |||
| 29 | { | |||
| 30 | Length i; | |||
| 31 | Table t = (Table) stoAlloc((unsigned) OB_Table9, sizeof(*t)); | |||
| 32 | t->hashFun = hash; | |||
| 33 | t->eqFun = eq; | |||
| 34 | t->info = 0; | |||
| 35 | t->count = 0; | |||
| 36 | t->buckc = buckc; | |||
| 37 | t->buckv = (struct TblSlot **) | |||
| 38 | stoAlloc((unsigned) OB_Other0, buckc*sizeof(struct TblSlot *)); | |||
| 39 | for (i = 0; i < buckc; i++) t->buckv[i] = 0; | |||
| 40 | return t; | |||
| 41 | } | |||
| 42 | ||||
| 43 | void | |||
| 44 | tblFreeDeeply(Table t, TblFreeKeyFun fk, TblFreeEltFun fe) | |||
| 45 | { | |||
| 46 | ||||
| 47 | struct TblSlot *b, *nb; | |||
| 48 | int i; | |||
| 49 | ||||
| 50 | for (i = 0; i < t->buckc; i++) { | |||
| 51 | for (b = t->buckv[i]; b; ) { | |||
| 52 | nb = b->next; | |||
| 53 | if (fk) fk(b->key); | |||
| 54 | if (fe) fe(b->elt); | |||
| 55 | stoFree((Pointer) b); | |||
| 56 | b = nb; | |||
| 57 | } | |||
| 58 | } | |||
| 59 | stoFree((Pointer) t->buckv); | |||
| 60 | stoFree((Pointer) t); | |||
| 61 | } | |||
| 62 | ||||
| 63 | void | |||
| 64 | tblFree(Table t) | |||
| 65 | { | |||
| 66 | struct TblSlot *b, *nb; | |||
| 67 | int i; | |||
| 68 | ||||
| 69 | for (i = 0; i < t->buckc; i++) | |||
| 70 | for (b = t->buckv[i]; b; ) { | |||
| 71 | nb = b->next; | |||
| 72 | stoFree((Pointer) b); | |||
| 73 | b = nb; | |||
| 74 | } | |||
| 75 | stoFree((Pointer) t->buckv); | |||
| 76 | stoFree((Pointer) t); | |||
| 77 | } | |||
| 78 | ||||
| 79 | Table | |||
| 80 | tblCopy(Table ot) | |||
| 81 | { | |||
| 82 | Table nt; | |||
| 83 | struct TblSlot *ob, *nb, **pnb; | |||
| 84 | int i; | |||
| 85 | ||||
| 86 | nt = tblNew0(ot->hashFun, ot->eqFun, ot->buckc); | |||
| 87 | nt->count = ot->count; | |||
| 88 | for (i = 0; i < ot->buckc; i++) { | |||
| 89 | pnb = nt->buckv + i; | |||
| 90 | for (ob = ot->buckv[i]; ob; ob = ob->next) { | |||
| 91 | nb = (struct TblSlot *) | |||
| 92 | stoAlloc((unsigned) OB_Other0, sizeof(*nb)); | |||
| 93 | nb->key = ob->key; | |||
| 94 | nb->elt = ob->elt; | |||
| 95 | nb->hash = ob->hash; | |||
| 96 | *pnb = nb; | |||
| 97 | pnb = &(nb->next); | |||
| 98 | } | |||
| 99 | *pnb = 0; | |||
| 100 | } | |||
| 101 | return nt; | |||
| 102 | } | |||
| 103 | ||||
| 104 | /* Given table, freeFun, testFun, apply freeFun to all (non-null) elements in | |||
| 105 | * table that satisfy testFun | |||
| 106 | */ | |||
| 107 | Table | |||
| 108 | tblRemoveIf(Table t, TblFreeEltFun fe, TblTestEltFun f) | |||
| 109 | { | |||
| 110 | struct TblSlot *b; | |||
| 111 | int i; | |||
| 112 | ||||
| 113 | for (i = 0; i < t->buckc; i++) | |||
| 114 | for (b = t->buckv[i]; b; b = b->next) | |||
| 115 | if (b->elt && f(b->elt)) { | |||
| 116 | fe(b->elt); | |||
| 117 | b->elt = NULL((void*)0); /* !! */ | |||
| 118 | } | |||
| 119 | return t; | |||
| 120 | } | |||
| 121 | ||||
| 122 | Table | |||
| 123 | tblNMap(TblMapEltFun f, Table t) | |||
| 124 | { | |||
| 125 | struct TblSlot *b; | |||
| 126 | int i; | |||
| 127 | ||||
| 128 | for (i = 0; i < t->buckc; i++) | |||
| 129 | for (b = t->buckv[i]; b; b = b->next) | |||
| 130 | b->elt = f(b->elt); | |||
| 131 | return t; | |||
| 132 | } | |||
| 133 | ||||
| 134 | ||||
| 135 | Length | |||
| 136 | tblSize(Table t) | |||
| 137 | { | |||
| 138 | return t->count; | |||
| 139 | } | |||
| 140 | ||||
| 141 | #if 0 | |||
| 142 | #define BUCKET_SEARCH(t,x,b,h,k,efun,ACTION){ register struct TblSlot *p = 0; do { if (b->hash == h) if (!efun || efun(k, b->key)) { if (p) { p->next = b-> next; b->next = t->buckv[x]; t->buckv[x] = b; } ACTION ; } p = b; b = b->next; } while (b); } { \ | |||
| 143 | register struct TblSlot *p = 0; \ | |||
| 144 | if (efun) { \ | |||
| 145 | do { \ | |||
| 146 | if (b->hash == h) \ | |||
| 147 | if (efun(k, b->key)) { \ | |||
| 148 | if (p) { \ | |||
| 149 | /* Move to front */ \ | |||
| 150 | p->next = b->next; \ | |||
| 151 | b->next = t->buckv[x]; \ | |||
| 152 | t->buckv[x] = b; \ | |||
| 153 | } \ | |||
| 154 | ACTION; \ | |||
| 155 | } \ | |||
| 156 | p = b; \ | |||
| 157 | b = b->next; \ | |||
| 158 | } while (b); \ | |||
| 159 | } \ | |||
| 160 | else { \ | |||
| 161 | do { \ | |||
| 162 | if (b->hash == h) { \ | |||
| 163 | if (p) { \ | |||
| 164 | /* Move to front */ \ | |||
| 165 | p->next = b->next; \ | |||
| 166 | b->next = t->buckv[x]; \ | |||
| 167 | t->buckv[x] = b; \ | |||
| 168 | } \ | |||
| 169 | ACTION; \ | |||
| 170 | } \ | |||
| 171 | p = b; \ | |||
| 172 | b = b->next; \ | |||
| 173 | } while (b); \ | |||
| 174 | } \ | |||
| 175 | } | |||
| 176 | #endif | |||
| 177 | ||||
| 178 | #define BUCKET_SEARCH(t,x,b,h,k,efun,ACTION){ register struct TblSlot *p = 0; do { if (b->hash == h) if (!efun || efun(k, b->key)) { if (p) { p->next = b-> next; b->next = t->buckv[x]; t->buckv[x] = b; } ACTION ; } p = b; b = b->next; } while (b); } { \ | |||
| 179 | register struct TblSlot *p = 0; \ | |||
| 180 | do { \ | |||
| 181 | if (b->hash == h) \ | |||
| 182 | if (!efun || efun(k, b->key)) { \ | |||
| 183 | if (p) { \ | |||
| 184 | /* Move to front */ \ | |||
| 185 | p->next = b->next; \ | |||
| 186 | b->next = t->buckv[x]; \ | |||
| 187 | t->buckv[x] = b; \ | |||
| 188 | } \ | |||
| 189 | ACTION; \ | |||
| 190 | } \ | |||
| 191 | p = b; \ | |||
| 192 | b = b->next; \ | |||
| 193 | } while (b); \ | |||
| 194 | } | |||
| 195 | ||||
| 196 | TblElt | |||
| 197 | tblElt(Table t, TblKey k, TblElt notFound) | |||
| 198 | { | |||
| 199 | register Hash h; | |||
| 200 | register int x; | |||
| 201 | register struct TblSlot *b; | |||
| 202 | register TblHashFun hfun = t->hashFun; | |||
| 203 | register TblEqFun efun = t->eqFun; | |||
| 204 | ||||
| 205 | h = hfun ? hfun(k) : (Hash) ptrCanon(k)((Pointer)(k)); | |||
| 206 | x = h % t->buckc; | |||
| 207 | b = t->buckv[x]; | |||
| 208 | ||||
| 209 | if (b) BUCKET_SEARCH(t,x,b,h,k,efun, return b->elt){ register struct TblSlot *p = 0; do { if (b->hash == h) if (!efun || efun(k, b->key)) { if (p) { p->next = b-> next; b->next = t->buckv[x]; t->buckv[x] = b; } return b->elt; } p = b; b = b->next; } while (b); }; | |||
| 210 | ||||
| 211 | return notFound; | |||
| 212 | } | |||
| 213 | ||||
| 214 | TblElt | |||
| 215 | tblSetElt(Table t, TblKey k, TblElt e) | |||
| 216 | { | |||
| 217 | register Hash h; | |||
| 218 | register int x; | |||
| 219 | register struct TblSlot *b; | |||
| 220 | register TblHashFun hfun = t->hashFun; | |||
| 221 | register TblEqFun efun = t->eqFun; | |||
| 222 | ||||
| 223 | h = hfun ? hfun(k) : (Hash) ptrCanon(k)((Pointer)(k)); | |||
| ||||
| 224 | x = h % t->buckc; | |||
| 225 | b = t->buckv[x]; | |||
| 226 | ||||
| 227 | if (b) BUCKET_SEARCH(t,x,b,h,k,efun, return b->elt = e){ register struct TblSlot *p = 0; do { if (b->hash == h) if (!efun || efun(k, b->key)) { if (p) { p->next = b-> next; b->next = t->buckv[x]; t->buckv[x] = b; } return b->elt = e; } p = b; b = b->next; } while (b); }; | |||
| 228 | ||||
| 229 | b = (struct TblSlot *) stoAlloc((unsigned) OB_Other0, sizeof(*b)); | |||
| 230 | b->key = k; | |||
| 231 | b->elt = e; | |||
| 232 | b->hash = h; | |||
| 233 | b->next = t->buckv[x]; | |||
| 234 | t->buckv[x] = b; | |||
| 235 | t->count++; | |||
| 236 | ||||
| 237 | if (t->count > TBL_MaxLoad5 * t->buckc) tblEnlarge(t); | |||
| 238 | ||||
| 239 | return e; | |||
| 240 | } | |||
| 241 | ||||
| 242 | ||||
| 243 | Table | |||
| 244 | tblDrop(Table t, TblKey k) | |||
| 245 | { | |||
| 246 | register Hash h; | |||
| 247 | register int x; | |||
| 248 | register struct TblSlot *b; | |||
| 249 | register TblHashFun hfun = t->hashFun; | |||
| 250 | register TblEqFun efun = t->eqFun; | |||
| 251 | ||||
| 252 | h = hfun ? hfun(k) : (Hash) ptrCanon(k)((Pointer)(k)); | |||
| 253 | x = h % t->buckc; | |||
| 254 | b = t->buckv[x]; | |||
| 255 | ||||
| 256 | if (b) BUCKET_SEARCH(t,x,b,h,k,efun, {{ register struct TblSlot *p = 0; do { if (b->hash == h) if (!efun || efun(k, b->key)) { if (p) { p->next = b-> next; b->next = t->buckv[x]; t->buckv[x] = b; } { t-> buckv[x] = b->next; t->count--; stoFree((Pointer) b); return t; }; } p = b; b = b->next; } while (b); } | |||
| 257 | t->buckv[x] = b->next;{ register struct TblSlot *p = 0; do { if (b->hash == h) if (!efun || efun(k, b->key)) { if (p) { p->next = b-> next; b->next = t->buckv[x]; t->buckv[x] = b; } { t-> buckv[x] = b->next; t->count--; stoFree((Pointer) b); return t; }; } p = b; b = b->next; } while (b); } | |||
| 258 | t->count--;{ register struct TblSlot *p = 0; do { if (b->hash == h) if (!efun || efun(k, b->key)) { if (p) { p->next = b-> next; b->next = t->buckv[x]; t->buckv[x] = b; } { t-> buckv[x] = b->next; t->count--; stoFree((Pointer) b); return t; }; } p = b; b = b->next; } while (b); } | |||
| 259 | stoFree((Pointer) b);{ register struct TblSlot *p = 0; do { if (b->hash == h) if (!efun || efun(k, b->key)) { if (p) { p->next = b-> next; b->next = t->buckv[x]; t->buckv[x] = b; } { t-> buckv[x] = b->next; t->count--; stoFree((Pointer) b); return t; }; } p = b; b = b->next; } while (b); } | |||
| 260 | return t;{ register struct TblSlot *p = 0; do { if (b->hash == h) if (!efun || efun(k, b->key)) { if (p) { p->next = b-> next; b->next = t->buckv[x]; t->buckv[x] = b; } { t-> buckv[x] = b->next; t->count--; stoFree((Pointer) b); return t; }; } p = b; b = b->next; } while (b); } | |||
| 261 | }){ register struct TblSlot *p = 0; do { if (b->hash == h) if (!efun || efun(k, b->key)) { if (p) { p->next = b-> next; b->next = t->buckv[x]; t->buckv[x] = b; } { t-> buckv[x] = b->next; t->count--; stoFree((Pointer) b); return t; }; } p = b; b = b->next; } while (b); }; | |||
| 262 | ||||
| 263 | return t; | |||
| 264 | } | |||
| 265 | ||||
| 266 | localstatic void | |||
| 267 | tblEnlarge(Table t) | |||
| 268 | { | |||
| 269 | register struct TblSlot **nbuckv, *b, *hd; | |||
| 270 | register int nbuckc, i, x; | |||
| 271 | ||||
| 272 | nbuckc = binPrime(cielLg(t->buckc)+1); | |||
| 273 | nbuckv = (struct TblSlot **) | |||
| 274 | stoAlloc((unsigned) OB_Other0, nbuckc*sizeof(struct TblSlot*)); | |||
| 275 | for (i = 0; i < nbuckc; i++) nbuckv[i] = 0; | |||
| 276 | ||||
| 277 | for (i = 0; i
| |||
| 278 | b = t->buckv[i]; | |||
| 279 | while (b) { | |||
| 280 | hd = b; | |||
| 281 | b = b->next; | |||
| 282 | ||||
| 283 | x = hd->hash % nbuckc; | |||
| ||||
| 284 | hd->next = nbuckv[x]; | |||
| 285 | nbuckv[x] = hd; | |||
| 286 | } | |||
| 287 | } | |||
| 288 | stoFree((Pointer) t->buckv); | |||
| 289 | t->buckc = nbuckc; | |||
| 290 | t->buckv = nbuckv; | |||
| 291 | } | |||
| 292 | ||||
| 293 | int | |||
| 294 | tblPrint(FILE *fout, Table t, TblPrKeyFun prk, TblPrEltFun pre) | |||
| 295 | { | |||
| 296 | struct TblSlot *b; | |||
| 297 | int cc, i, j; | |||
| 298 | ||||
| 299 | cc = fprintf(fout, "Table("); | |||
| 300 | for (i = 0; i < t->buckc; i++) { | |||
| 301 | cc += fprintf(fout, "[%d] ", i); | |||
| 302 | for (j = 0, b = t->buckv[i]; b; j++, b = b->next) { | |||
| 303 | if (j > 0) | |||
| 304 | cc += fprintf(fout, ", "); | |||
| 305 | if (prk) | |||
| 306 | cc += prk(fout, b->key); | |||
| 307 | if (pre) { | |||
| 308 | cc += fprintf(fout, "="); | |||
| 309 | cc += pre(fout, b->elt); | |||
| 310 | } | |||
| 311 | } | |||
| 312 | cc += fprintf(fout, ";"); | |||
| 313 | } | |||
| 314 | cc += fprintf(fout, ")"); | |||
| 315 | return cc; | |||
| 316 | } | |||
| 317 | ||||
| 318 | #ifndef FOAM_RTS | |||
| 319 | int | |||
| 320 | tblColumnPrint(FILE *fout, Table t, TblPrKeyFun prk, TblPrEltFun pre) | |||
| 321 | { | |||
| 322 | struct TblSlot *b; | |||
| 323 | int cc, i; | |||
| 324 | ||||
| 325 | /* print table entries in a single column */ | |||
| 326 | ||||
| 327 | cc = fnewline(fout); | |||
| 328 | for (i = 0; i < t->buckc; i++) { | |||
| 329 | for (b = t->buckv[i]; b; b = b->next) { | |||
| 330 | if (prk) | |||
| 331 | cc += prk(fout, b->key); | |||
| 332 | if (pre) { | |||
| 333 | if (prk) | |||
| 334 | cc += fprintf(fout, "="); | |||
| 335 | cc += pre(fout, b->elt); | |||
| 336 | cc += fnewline(fout); | |||
| 337 | } | |||
| 338 | } | |||
| 339 | } | |||
| 340 | return cc; | |||
| 341 | } | |||
| 342 | ||||
| 343 | #endif | |||
| 344 | ||||
| 345 | int | |||
| 346 | _tblITER(TableIterator *pit, Table t) | |||
| 347 | { | |||
| 348 | pit->curr = t->buckv; | |||
| 349 | pit->last = t->buckv + t->buckc - 1; | |||
| 350 | pit->link = t->buckv[0]; | |||
| 351 | ||||
| 352 | if (pit->link) return 1; | |||
| 353 | ||||
| 354 | /* Skip over initial empty buckets. */ | |||
| 355 | return _tblSTEP(pit); | |||
| 356 | } | |||
| 357 | ||||
| 358 | int | |||
| 359 | _tblSTEP(TableIterator *pit) | |||
| 360 | { | |||
| 361 | /* Skip to next non-empty bucket. */ | |||
| 362 | do { | |||
| 363 | pit->curr++; | |||
| 364 | if (pit->curr > pit->last) return 0; | |||
| 365 | } while (!pit->curr[0]); | |||
| 366 | ||||
| 367 | pit->link = pit->curr[0]; | |||
| 368 | return 1; | |||
| 369 | } |