Int HG_(cardinalityWS) ( WordSetU* wsu, WordSet ws ) { WordVec* wv; tl_assert(wsu); wv = do_ix2vec( wsu, ws ); tl_assert(wv->size >= 0); return wv->size; }
Bool HG_(isSingletonWS) ( WordSetU* wsu, WordSet ws, Word w ) { WordVec* wv; tl_assert(wsu); wsu->n_isSingleton++; wv = do_ix2vec( wsu, ws ); return (Bool)(wv->size == 1 && wv->words[0] == w); }
Word HG_(anyElementOfWS) ( WordSetU* wsu, WordSet ws ) { WordVec* wv; tl_assert(wsu); wsu->n_anyElementOf++; wv = do_ix2vec( wsu, ws ); tl_assert(wv->size >= 1); return wv->words[0]; }
void HG_(getPayloadWS) ( /*OUT*/Word** words, /*OUT*/Word* nWords, WordSetU* wsu, WordSet ws ) { WordVec* wv; tl_assert(wsu); wv = do_ix2vec( wsu, ws ); tl_assert(wv->size >= 0); *nWords = wv->size; *words = wv->words; }
void HG_(getPayloadWS) ( UWord** words, UWord* nWords, WordSetU* wsu, WordSet ws ) { WordVec* wv; if (HG_DEBUG) VG_(printf)("getPayloadWS %s %d\n", wsu->cc, (Int)ws); tl_assert(wsu); wv = do_ix2vec( wsu, ws ); tl_assert(wv->size >= 0); *nWords = wv->size; *words = wv->words; }
Bool HG_(elemWS) ( WordSetU* wsu, WordSet ws, Word w ) { Int i; WordVec* wv = do_ix2vec( wsu, ws ); wsu->n_elem++; for (i = 0; i < wv->size; i++) { if (wv->words[i] == w) return True; } return False; }
void show_WS ( WordSetU* wsu, WordSet ws ) { Int i; WordVec* wv = do_ix2vec( wsu, ws ); VG_(printf)("#%u{", ws); for (i = 0; i < wv->size; i++) { VG_(printf)("%lu", wv->words[i]); if (i < wv->size-1) VG_(printf)(","); } VG_(printf)("}\n"); }
Bool HG_(isEmptyWS) ( WordSetU* wsu, WordSet ws ) { WordVec* wv = do_ix2vec( wsu, ws ); wsu->n_isEmpty++; if (wv->size == 0) { tl_assert(ws == wsu->empty); return True; } else { tl_assert(ws != wsu->empty); return False; } }
WordSet HG_(delFromWS) ( WordSetU* wsu, WordSet ws, Word w ) { Int i, j, k; WordVec* wv_new; WordSet result = (WordSet)(-1); /* bogus */ WordVec* wv = do_ix2vec( wsu, ws ); wsu->n_del++; /* special case empty set */ if (wv->size == 0) { tl_assert(ws == wsu->empty); return ws; } WCache_LOOKUP_AND_RETURN(WordSet, wsu->cache_delFrom, ws, w); wsu->n_del_uncached++; /* If not already present, this is a no-op. */ for (i = 0; i < wv->size; i++) { if (wv->words[i] == w) break; } if (i == wv->size) { result = ws; goto out; } /* So w is present in ws, and the new set will be one element smaller. */ tl_assert(i >= 0 && i < wv->size); tl_assert(wv->size > 0); wv_new = new_WV_of_size( wsu, wv->size - 1 ); j = k = 0; for (; j < wv->size; j++) { if (j == i) continue; wv_new->words[k++] = wv->words[j]; } tl_assert(k == wv_new->size); result = add_or_dealloc_WordVec( wsu, wv_new ); if (wv->size == 1) { tl_assert(result == wsu->empty); } out: WCache_UPDATE(wsu->cache_delFrom, ws, w, result); return result; }
void HG_(ppWS) ( WordSetU* wsu, WordSet ws ) { Int i; WordVec* wv; tl_assert(wsu); wv = do_ix2vec( wsu, ws ); VG_(printf)("{"); for (i = 0; i < wv->size; i++) { VG_(printf)("%p", (void*)wv->words[i]); if (i < wv->size-1) VG_(printf)(","); } VG_(printf)("}"); }
WordSet HG_(delFromWS) ( WordSetU* wsu, WordSet ws, UWord w ) { UWord i, j, k; WordVec* wv_new; WordSet result = (WordSet)(-1); WordVec* wv = do_ix2vec( wsu, ws ); wsu->n_del++; if (wv->size == 0) { tl_assert(ws == wsu->empty); return ws; } WCache_LOOKUP_AND_RETURN(WordSet, wsu->cache_delFrom, ws, w); wsu->n_del_uncached++; for (i = 0; i < wv->size; i++) { if (wv->words[i] == w) break; } if (i == wv->size) { result = ws; goto out; } tl_assert(i >= 0 && i < wv->size); tl_assert(wv->size > 0); wv_new = new_WV_of_size( wsu, wv->size - 1 ); j = k = 0; for (; j < wv->size; j++) { if (j == i) continue; wv_new->words[k++] = wv->words[j]; } tl_assert(k == wv_new->size); result = add_or_dealloc_WordVec( wsu, wv_new ); if (wv->size == 1) { tl_assert(result == wsu->empty); } out: WCache_UPDATE(wsu->cache_delFrom, ws, w, result); return result; }
Bool HG_(saneWS_SLOW) ( WordSetU* wsu, WordSet ws ) { WordVec* wv; Int i; if (wsu == NULL) return False; if (ws < 0 || ws >= wsu->ix2vec_used) return False; wv = do_ix2vec( wsu, ws ); /* can never happen .. do_ix2vec will assert instead. Oh well. */ if (wv->owner != wsu) return False; if (wv->size < 0) return False; if (wv->size > 0) { for (i = 0; i < wv->size-1; i++) { if (wv->words[i] >= wv->words[i+1]) return False; } } return True; }
Bool HG_(saneWS_SLOW) ( WordSetU* wsu, WordSet ws ) { WordVec* wv; UWord i; if (wsu == NULL) return False; if (ws < 0 || ws >= wsu->ix2vec_used) return False; wv = do_ix2vec( wsu, ws ); if (wv->owner != wsu) return False; if (wv->size < 0) return False; if (wv->size > 0) { for (i = 0; i < wv->size-1; i++) { if (wv->words[i] >= wv->words[i+1]) return False; } } return True; }
WordSet HG_(addToWS) ( WordSetU* wsu, WordSet ws, Word w ) { Int k, j; WordVec* wv_new; WordVec* wv; WordSet result = (WordSet)(-1); /* bogus */ wsu->n_add++; WCache_LOOKUP_AND_RETURN(WordSet, wsu->cache_addTo, ws, w); wsu->n_add_uncached++; /* If already present, this is a no-op. */ wv = do_ix2vec( wsu, ws ); for (k = 0; k < wv->size; k++) { if (wv->words[k] == w) { result = ws; goto out; } } /* Ok, not present. Build a new one ... */ wv_new = new_WV_of_size( wsu, wv->size + 1 ); k = j = 0; for (; k < wv->size && wv->words[k] < w; k++) { wv_new->words[j++] = wv->words[k]; } wv_new->words[j++] = w; for (; k < wv->size; k++) { tl_assert(wv->words[k] > w); wv_new->words[j++] = wv->words[k]; } tl_assert(j == wv_new->size); /* Find any existing copy, or add the new one. */ result = add_or_dealloc_WordVec( wsu, wv_new ); tl_assert(result != (WordSet)(-1)); out: WCache_UPDATE(wsu->cache_addTo, ws, w, result); return result; }
WordSet HG_(addToWS) ( WordSetU* wsu, WordSet ws, UWord w ) { UWord k, j; WordVec* wv_new; WordVec* wv; WordSet result = (WordSet)(-1); wsu->n_add++; WCache_LOOKUP_AND_RETURN(WordSet, wsu->cache_addTo, ws, w); wsu->n_add_uncached++; wv = do_ix2vec( wsu, ws ); for (k = 0; k < wv->size; k++) { if (wv->words[k] == w) { result = ws; goto out; } } wv_new = new_WV_of_size( wsu, wv->size + 1 ); k = j = 0; for (; k < wv->size && wv->words[k] < w; k++) { wv_new->words[j++] = wv->words[k]; } wv_new->words[j++] = w; for (; k < wv->size; k++) { tl_assert(wv->words[k] > w); wv_new->words[j++] = wv->words[k]; } tl_assert(j == wv_new->size); result = add_or_dealloc_WordVec( wsu, wv_new ); tl_assert(result != (WordSet)(-1)); out: WCache_UPDATE(wsu->cache_addTo, ws, w, result); return result; }
WordSet HG_(minusWS) ( WordSetU* wsu, WordSet ws1, WordSet ws2 ) { Int i1, i2, k, sz; WordSet ws_new = (WordSet)(-1); /* bogus */ WordVec* wv_new; WordVec* wv1; WordVec* wv2; wsu->n_minus++; WCache_LOOKUP_AND_RETURN(WordSet, wsu->cache_minus, ws1, ws2); wsu->n_minus_uncached++; wv1 = do_ix2vec( wsu, ws1 ); wv2 = do_ix2vec( wsu, ws2 ); sz = 0; i1 = i2 = 0; while (1) { if (i1 >= wv1->size || i2 >= wv2->size) break; if (wv1->words[i1] < wv2->words[i2]) { sz++; i1++; } else if (wv1->words[i1] > wv2->words[i2]) { i2++; } else { i1++; i2++; } } tl_assert(i1 <= wv1->size); tl_assert(i2 <= wv2->size); tl_assert(i1 == wv1->size || i2 == wv2->size); if (i2 == wv2->size && i1 < wv1->size) { sz += (wv1->size - i1); } wv_new = new_WV_of_size( wsu, sz ); k = 0; i1 = i2 = 0; while (1) { if (i1 >= wv1->size || i2 >= wv2->size) break; if (wv1->words[i1] < wv2->words[i2]) { wv_new->words[k++] = wv1->words[i1]; i1++; } else if (wv1->words[i1] > wv2->words[i2]) { i2++; } else { i1++; i2++; } } tl_assert(i1 <= wv1->size); tl_assert(i2 <= wv2->size); tl_assert(i1 == wv1->size || i2 == wv2->size); if (i2 == wv2->size && i1 < wv1->size) { while (i1 < wv1->size) wv_new->words[k++] = wv1->words[i1++]; } tl_assert(k == sz); ws_new = add_or_dealloc_WordVec( wsu, wv_new ); if (sz == 0) { tl_assert(ws_new == wsu->empty); } tl_assert(ws_new != (WordSet)(-1)); WCache_UPDATE(wsu->cache_minus, ws1, ws2, ws_new); return ws_new; }
WordSet HG_(intersectWS) ( WordSetU* wsu, WordSet ws1, WordSet ws2 ) { Int i1, i2, k, sz; WordSet ws_new = (WordSet)(-1); /* bogus */ WordVec* wv_new; WordVec* wv1; WordVec* wv2; wsu->n_intersect++; /* Deal with an obvious case fast. */ if (ws1 == ws2) return ws1; /* Since intersect(x,y) == intersect(y,x), convert both variants to the same query. This reduces the number of variants the cache has to deal with. */ if (ws1 > ws2) { WordSet wst = ws1; ws1 = ws2; ws2 = wst; } WCache_LOOKUP_AND_RETURN(WordSet, wsu->cache_intersect, ws1, ws2); wsu->n_intersect_uncached++; wv1 = do_ix2vec( wsu, ws1 ); wv2 = do_ix2vec( wsu, ws2 ); sz = 0; i1 = i2 = 0; while (1) { if (i1 >= wv1->size || i2 >= wv2->size) break; if (wv1->words[i1] < wv2->words[i2]) { i1++; } else if (wv1->words[i1] > wv2->words[i2]) { i2++; } else { sz++; i1++; i2++; } } tl_assert(i1 <= wv1->size); tl_assert(i2 <= wv2->size); tl_assert(i1 == wv1->size || i2 == wv2->size); wv_new = new_WV_of_size( wsu, sz ); k = 0; i1 = i2 = 0; while (1) { if (i1 >= wv1->size || i2 >= wv2->size) break; if (wv1->words[i1] < wv2->words[i2]) { i1++; } else if (wv1->words[i1] > wv2->words[i2]) { i2++; } else { wv_new->words[k++] = wv1->words[i1]; i1++; i2++; } } tl_assert(i1 <= wv1->size); tl_assert(i2 <= wv2->size); tl_assert(i1 == wv1->size || i2 == wv2->size); tl_assert(k == sz); ws_new = add_or_dealloc_WordVec( wsu, wv_new ); if (sz == 0) { tl_assert(ws_new == wsu->empty); } tl_assert(ws_new != (WordSet)(-1)); WCache_UPDATE(wsu->cache_intersect, ws1, ws2, ws_new); return ws_new; }
WordSet HG_(unionWS) ( WordSetU* wsu, WordSet ws1, WordSet ws2 ) { Int i1, i2, k, sz; WordVec* wv_new; WordVec* wv1 = do_ix2vec( wsu, ws1 ); WordVec* wv2 = do_ix2vec( wsu, ws2 ); wsu->n_union++; sz = 0; i1 = i2 = 0; while (1) { if (i1 >= wv1->size || i2 >= wv2->size) break; sz++; if (wv1->words[i1] < wv2->words[i2]) { i1++; } else if (wv1->words[i1] > wv2->words[i2]) { i2++; } else { i1++; i2++; } } tl_assert(i1 <= wv1->size); tl_assert(i2 <= wv2->size); tl_assert(i1 == wv1->size || i2 == wv2->size); if (i1 == wv1->size && i2 < wv2->size) { sz += (wv2->size - i2); } if (i2 == wv2->size && i1 < wv1->size) { sz += (wv1->size - i1); } wv_new = new_WV_of_size( wsu, sz ); k = 0; i1 = i2 = 0; while (1) { if (i1 >= wv1->size || i2 >= wv2->size) break; if (wv1->words[i1] < wv2->words[i2]) { wv_new->words[k++] = wv1->words[i1]; i1++; } else if (wv1->words[i1] > wv2->words[i2]) { wv_new->words[k++] = wv2->words[i2]; i2++; } else { wv_new->words[k++] = wv1->words[i1]; i1++; i2++; } } tl_assert(i1 <= wv1->size); tl_assert(i2 <= wv2->size); tl_assert(i1 == wv1->size || i2 == wv2->size); if (i1 == wv1->size && i2 < wv2->size) { while (i2 < wv2->size) wv_new->words[k++] = wv2->words[i2++]; } if (i2 == wv2->size && i1 < wv1->size) { while (i1 < wv1->size) wv_new->words[k++] = wv1->words[i1++]; } tl_assert(k == sz); return add_or_dealloc_WordVec( wsu, wv_new ); }
WordSet HG_(intersectWS) ( WordSetU* wsu, WordSet ws1, WordSet ws2 ) { UWord i1, i2, k, sz; WordSet ws_new = (WordSet)(-1); WordVec* wv_new; WordVec* wv1; WordVec* wv2; wsu->n_intersect++; if (ws1 == ws2) return ws1; if (ws1 > ws2) { WordSet wst = ws1; ws1 = ws2; ws2 = wst; } WCache_LOOKUP_AND_RETURN(WordSet, wsu->cache_intersect, ws1, ws2); wsu->n_intersect_uncached++; wv1 = do_ix2vec( wsu, ws1 ); wv2 = do_ix2vec( wsu, ws2 ); sz = 0; i1 = i2 = 0; while (1) { if (i1 >= wv1->size || i2 >= wv2->size) break; if (wv1->words[i1] < wv2->words[i2]) { i1++; } else if (wv1->words[i1] > wv2->words[i2]) { i2++; } else { sz++; i1++; i2++; } } tl_assert(i1 <= wv1->size); tl_assert(i2 <= wv2->size); tl_assert(i1 == wv1->size || i2 == wv2->size); wv_new = new_WV_of_size( wsu, sz ); k = 0; i1 = i2 = 0; while (1) { if (i1 >= wv1->size || i2 >= wv2->size) break; if (wv1->words[i1] < wv2->words[i2]) { i1++; } else if (wv1->words[i1] > wv2->words[i2]) { i2++; } else { wv_new->words[k++] = wv1->words[i1]; i1++; i2++; } } tl_assert(i1 <= wv1->size); tl_assert(i2 <= wv2->size); tl_assert(i1 == wv1->size || i2 == wv2->size); tl_assert(k == sz); ws_new = add_or_dealloc_WordVec( wsu, wv_new ); if (sz == 0) { tl_assert(ws_new == wsu->empty); } tl_assert(ws_new != (WordSet)(-1)); WCache_UPDATE(wsu->cache_intersect, ws1, ws2, ws_new); return ws_new; }