public override T[] ToArray() { T[] res = new T[size]; int index = 0; #if !REFBUCKET if (defaultvalid) res[index++] = defaultitem; #endif for (int i = 0; i < table.Length; i++) { Bucket b = table[i]; #if LINEARPROBING #if REFBUCKET if (b != null) res[index++] = b.item; #else if (!isnull(b.item)) res[index++] = b.item; #endif #else #if REFBUCKET while (b != null) { res[index++] = b.item; b = b.overflow; } #else if (!isnull(b.item)) { res[index++] = b.item; OverflowBucket ob = b.overflow; while (ob != null) { res[index++] = ob.item; ob = ob.overflow; } } #endif #endif } Debug.Assert(size == index); return res; }
private bool remove(ref T item) { if (size == 0) return false; #if LINEARPROBING #if REFBUCKET int hashval = gethashcode(item); int index = hv2i(hashval); Bucket b = table[index]; while (b != null) { if (equals(item, b.item)) { //ref item = table[index].item; table[index] = null; //Algorithm R int j = (index + 1) & indexmask; b = table[j]; while (b != null) { int k = hv2i(b.hashval); if ((k <= index && index < j) || (index < j && j < k) || (j < k && k <= index)) //if (index > j ? (j < k && k <= index): (k <= index || j < k) ) { table[index] = b; table[j] = null; index = j; } j = (j + 1) & indexmask; b = table[j]; } goto found; } b = table[index = indexmask & (index + 1)]; } return false; #else if (isnull(item)) { if (!defaultvalid) return false; //ref item = defaultitem; defaultvalid = false; defaultitem = default(T); //No spaceleaks! } else { int hashval = gethashcode(item); int index = hv2i(hashval); T t = table[index].item; while (!isnull(t)) { if (equals(item, t)) { //ref item = table[index].item; table[index].item = default(T); //algorithm R int j = (index + 1) & indexmask; Bucket b = table[j]; while (!isnull(b.item)) { int k = hv2i(b.hashval); if ((k <= index && index < j) || (index < j && j < k) || (j < k && k <= index)) { table[index] = b; table[j].item = default(T); index = j; } j = (j + 1) & indexmask; b = table[j]; } goto found; } t = table[index = indexmask & (index + 1)].item; } return false; } #endif found: #else #if REFBUCKET int hashval = gethashcode(item); int index = hv2i(hashval); Bucket b = table[index], bold; if (b == null) return false; if (equals(item, b.item)) { //ref item = b.item; table[index] = b.overflow; } else { bold = b; b = b.overflow; while (b != null && !equals(item, b.item)) { bold = b; b = b.overflow; } if (b == null) return false; //ref item = b.item; bold.overflow = b.overflow; } #else if (isnull(item)) { if (!defaultvalid) return false; //ref item = defaultitem; defaultvalid = false; defaultitem = default(T); //No spaceleaks! } else { int hashval = gethashcode(item); int index = hv2i(hashval); Bucket b = table[index]; OverflowBucket ob = b.overflow; if (equals(item, b.item)) { //ref item = b.item; if (ob == null) { table[index] = new Bucket(); } else { b = new Bucket(ob.item, ob.hashval); b.overflow = ob.overflow; table[index] = b; } } else { if (ob == null) return false; if (equals(item, ob.item)) { //ref item=ob.item; table[index].overflow = ob.overflow; } else { while (ob.overflow != null) if (equals(item, ob.overflow.item)) { //ref item = ob.overflow.item; break; } else ob = ob.overflow; if (ob.overflow == null) return false; ob.overflow = ob.overflow.overflow; } } } #endif #endif size--; return true; }
/// <summary> /// Search for an item equal (according to itemequalityComparer) to the supplied item. /// </summary> /// <param name="item"></param> /// <param name="add">If true, add item to table if not found.</param> /// <param name="update">If true, update table entry if item found.</param> /// <param name="raise">If true raise events</param> /// <returns>True if found</returns> private bool searchoradd(ref T item, bool add, bool update, bool raise) { #if LINEARPROBING #if REFBUCKET int hashval = gethashcode(item); int i = hv2i(hashval); Bucket b = table[i]; while (b != null) { T olditem = b.item; if (equals(olditem, item)) { if (update) b.item = item; else item = olditem; if (raise && update) raiseForUpdate(item, olditem); return true; } b = table[i = indexmask & (i + 1)]; } if (!add) goto notfound; table[i] = new Bucket(item, hashval); #else if (isnull(item)) { if (defaultvalid) { T olditem = defaultitem; if (update) defaultitem = item; else item = defaultitem; if (raise && update) raiseForUpdate(item, olditem); return true; } if (!add) goto notfound; defaultvalid = true; defaultitem = item; } else { int hashval = gethashcode(item); int i = hv2i(hashval); T t = table[i].item; while (!isnull(t)) { if (equals(t, item)) { if (update) table[i].item = item; else item = t; if (raise && update) raiseForUpdate(item, t); return true; } t = table[i = indexmask & (i + 1)].item; } if (!add) goto notfound; table[i] = new Bucket(item, hashval); } #endif #else #if REFBUCKET int hashval = gethashcode(item); int i = hv2i(hashval); Bucket b = table[i], bold = null; if (b != null) { while (b != null) { T olditem = b.item; if (equals(olditem, item)) { if (update) { b.item = item; } if (raise && update) raiseForUpdate(item, olditem); // bug20071112: item = olditem; return true; } bold = b; b = b.overflow; } if (!add) goto notfound; bold.overflow = new Bucket(item, hashval, null); } else { if (!add) goto notfound; table[i] = new Bucket(item, hashval, null); } #else if (isnull(item)) { if (defaultvalid) { T olditem = defaultitem; if (update) defaultitem = item; else item = defaultitem; if (raise && update) raiseForUpdate(item, olditem); return true; } if (!add) goto notfound; defaultvalid = true; defaultitem = item; } else { int hashval = gethashcode(item); int i = hv2i(hashval); Bucket b = table[i]; if (!isnull(b.item)) { if (equals(b.item, item)) { if (update) table[i].item = item; else item = b.item; if (raise && update) raiseForUpdate(item, b.item); return true; } OverflowBucket ob = table[i].overflow; if (ob == null) { if (!add) goto notfound; table[i].overflow = new OverflowBucket(item, hashval, null); } else { T olditem = ob.item; while (ob.overflow != null) { if (equals(item, olditem)) { if (update) ob.item = item; else item = olditem; if (raise && update) raiseForUpdate(item, olditem); return true; } ob = ob.overflow; olditem = ob.item; } if (equals(item, olditem)) { if (update) ob.item = item; else item = olditem; if (raise && update) raiseForUpdate(item, olditem); return true; } if (!add) goto notfound; ob.overflow = new OverflowBucket(item, hashval, null); } } else { if (!add) goto notfound; table[i] = new Bucket(item, hashval); } } #endif #endif size++; if (size > resizethreshhold) expand(); notfound: if (raise && add) raiseForAdd(item); if (update) item = default(T); return false; }
void resize(int bits) { //Console.WriteLine(String.Format("Resize to {0} bits", bits)); this.bits = bits; bitsc = 32 - bits; indexmask = (1 << bits) - 1; Bucket[] newtable = new Bucket[indexmask + 1]; for (int i = 0, s = table.Length; i < s; i++) { Bucket b = table[i]; #if LINEARPROBING #if REFBUCKET if (b != null) { int j = hv2i(b.hashval); while (newtable[j] != null) { j = indexmask & (j + 1); } newtable[j] = b; } #else if (!isnull(b.item)) { int j = hv2i(b.hashval); while (!isnull(newtable[j].item)) { j = indexmask & (j + 1); } newtable[j] = b; } #endif #else #if REFBUCKET while (b != null) { int j = hv2i(b.hashval); newtable[j] = new Bucket(b.item, b.hashval, newtable[j]); b = b.overflow; } #else if (!isnull(b.item)) { insert(b.item, b.hashval, newtable); OverflowBucket ob = b.overflow; while (ob != null) { insert(ob.item, ob.hashval, newtable); ob = ob.overflow; } } #endif #endif } table = newtable; resizethreshhold = (int)(table.Length * fillfactor); //Console.WriteLine(String.Format("Resize to {0} bits done", bits)); }
internal OverflowBucket(T item, int hashval, OverflowBucket overflow) { this.item = item; this.hashval = hashval; this.overflow = overflow; }
public ISortedDictionary<int, int> BucketCostDistribution() { TreeDictionary<int, int> res = new TreeDictionary<int, int>(); #if LINEARPROBING int count = 0; #if REFBUCKET while (table[count] != null) #else while (!isnull(table[count].item)) #endif count++; for (int i = table.Length - 1; i >= 0; i--) { #if REFBUCKET if (table[i] != null) #else if (!isnull(table[i].item)) #endif count++; else count = 0; if (res.Contains(count)) res[count]++; else res[count] = 1; } return res; #else for (int i = 0, s = table.Length; i < s; i++) { int count = 0; #if REFBUCKET Bucket b = table[i]; while (b != null) { count++; b = b.overflow; } #else Bucket b = table[i]; if (!isnull(b.item)) { count = 1; OverflowBucket ob = b.overflow; while (ob != null) { count++; ob = ob.overflow; } } #endif if (res.Contains(count)) res[count]++; else res[count] = 1; } return res; #endif }
public virtual bool Check() { int count = 0; #if LINEARPROBING int lasthole = table.Length - 1; #if REFBUCKET while (lasthole >= 0 && table[lasthole] != null) #else while (lasthole >= 0 && !isnull(table[lasthole].item)) #endif { lasthole--; count++; } if (lasthole < 0) { Console.WriteLine("Table is completely filled!"); return false; } for (int cellindex = lasthole + 1, s = table.Length; cellindex < s; cellindex++) { Bucket b = table[cellindex]; int hashindex = hv2i(b.hashval); if (hashindex <= lasthole || hashindex > cellindex) { Console.WriteLine("Bad cell item={0}, hashval={1}, hashindex={2}, cellindex={3}, lasthole={4}", b.item, b.hashval, hashindex, cellindex, lasthole); return false; } } int latesthole = -1; for (int cellindex = 0; cellindex < lasthole; cellindex++) { Bucket b = table[cellindex]; #if REFBUCKET if (b != null) #else if (!isnull(b.item)) #endif { count++; int hashindex = hv2i(b.hashval); if (cellindex < hashindex && hashindex <= lasthole) { Console.WriteLine("Bad cell item={0}, hashval={1}, hashindex={2}, cellindex={3}, latesthole={4}", b.item, b.hashval, hashindex, cellindex, latesthole); return false; } } else { latesthole = cellindex; break; } } for (int cellindex = latesthole + 1; cellindex < lasthole; cellindex++) { Bucket b = table[cellindex]; #if REFBUCKET if (b != null) #else if (!isnull(b.item)) #endif { count++; int hashindex = hv2i(b.hashval); if (hashindex <= latesthole || cellindex < hashindex) { Console.WriteLine("Bad cell item={0}, hashval={1}, hashindex={2}, cellindex={3}, latesthole={4}", b.item, b.hashval, hashindex, cellindex, latesthole); return false; } } else { latesthole = cellindex; } } return true; #else bool retval = true; if (bitsc != 32 - bits) { Console.WriteLine("bitsc != 32 - bits ({0}, {1})", bitsc, bits); retval = false; } if (indexmask != (1 << bits) - 1) { Console.WriteLine("indexmask != (1 << bits) - 1 ({0}, {1})", indexmask, bits); retval = false; } if (table.Length != indexmask + 1) { Console.WriteLine("table.Length != indexmask + 1 ({0}, {1})", table.Length, indexmask); retval = false; } if (bitsc != 32 - bits) { Console.WriteLine("resizethreshhold != (int)(table.Length * fillfactor) ({0}, {1}, {2})", resizethreshhold, table.Length, fillfactor); retval = false; } for (int i = 0, s = table.Length; i < s; i++) { int level = 0; Bucket b = table[i]; #if REFBUCKET while (b != null) { if (i != hv2i(b.hashval)) { Console.WriteLine("Bad cell item={0}, hashval={1}, index={2}, level={3}", b.item, b.hashval, i, level); retval = false; } count++; level++; b = b.overflow; } #else if (!isnull(b.item)) { count++; if (i != hv2i(b.hashval)) { Console.WriteLine("Bad cell item={0}, hashval={1}, index={2}, level={3}", b.item, b.hashval, i, level); retval = false; } OverflowBucket ob = b.overflow; while (ob != null) { level++; count++; if (i != hv2i(ob.hashval)) { Console.WriteLine("Bad cell item={0}, hashval={1}, index={2}, level={3}", b.item, b.hashval, i, level); retval = false; } ob = ob.overflow; } } #endif } if (count != size) { Console.WriteLine("size({0}) != count({1})", size, count); retval = false; } return retval; #endif }
public override SCG.IEnumerator<T> GetEnumerator() { int index = -1; int mystamp = stamp; int len = table.Length; #if LINEARPROBING #if REFBUCKET while (++index < len) { if (mystamp != stamp) throw new CollectionModifiedException(); if (table[index] != null) yield return table[index].item; } #else if (defaultvalid) yield return defaultitem; while (++index < len) { if (mystamp != stamp) throw new CollectionModifiedException(); T item = table[index].item; if (!isnull(item)) yield return item; } #endif #else #if REFBUCKET Bucket b = null; #else OverflowBucket ob = null; if (defaultvalid) yield return defaultitem; #endif while (true) { if (mystamp != stamp) throw new CollectionModifiedException(); #if REFBUCKET if (b == null || b.overflow == null) { do { if (++index >= len) yield break; } while (table[index] == null); b = table[index]; yield return b.item; } else { b = b.overflow; yield return b.item; } #else if (ob != null && ob.overflow != null) { ob = ob.overflow; yield return ob.item; } else if (index >= 0 && ob == null && (ob = table[index].overflow) != null) { yield return ob.item; } else { do { if (++index >= len) yield break; } while (isnull(table[index].item)); yield return table[index].item; ob = null; } #endif } #endif }