Skip to content

Instantly share code, notes, and snippets.

@mjs3339
Last active November 25, 2018 08:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjs3339/34a84eefb9a48b375a7b94f238b42436 to your computer and use it in GitHub Desktop.
Save mjs3339/34a84eefb9a48b375a7b94f238b42436 to your computer and use it in GitHub Desktop.
C# BigSet a Generic Basic Hash Set of Objects. Set Can Exceed 2GB on 64Bit Systems
[Serializable]
public class BigSet<T>
{
internal IBigEqualityComparer<T> _comparer;
internal BigArray<ulong> _hashBuckets;
internal BigArray<Slot> _slots;
internal ulong Count;
internal ulong Position;
internal int Version;
public BigSet() : this(BigArray<T>.Granularity, new BigComparer<T>())
{
}
public BigSet(ulong size) : this(size, new BigComparer<T>())
{
if(size < BigArray<T>.Granularity)
size = BigArray<T>.Granularity;
}
public BigSet(ulong size, IBigEqualityComparer<T> comparer)
{
if(size < BigArray<T>.Granularity)
size = BigArray<T>.Granularity;
if(comparer == null)
comparer = new BigComparer<T>();
_comparer = comparer;
_hashBuckets = new BigArray<ulong>(size);
for(ulong i = 0; i < _hashBuckets.Length; i++)
_hashBuckets[i] = ulong.MaxValue;
_slots = new BigArray<Slot>(size);
Count = 0;
Version = 0;
Position = ulong.MaxValue;
}
public T this[ulong index]
{
get
{
if(index > Count)
throw new Exception($"Getter: Index out of bounds {index} must be less than {Count}");
return _slots[index].value;
}
}
public bool Add(T item)
{
return Insert(item, true);
}
public bool Contains(T item)
{
var hashCode = (ulong) _comparer.GetHashCode(item) & long.MaxValue;
for(var position = _hashBuckets[hashCode % _hashBuckets.Length]; position != ulong.MaxValue; position = _slots[position].next)
if(_slots[position].hashCode == hashCode && _comparer.Equals(_slots[position].value, item))
{
Position = position;
return true;
}
Position = ulong.MaxValue;
return false;
}
internal bool Insert(T item, bool add)
{
var hashCode = (ulong) _comparer.GetHashCode(item) & long.MaxValue;
for(var position = _hashBuckets[hashCode % _hashBuckets.Length]; position != ulong.MaxValue; position = _slots[position].next)
if(_slots[position].hashCode == hashCode && _comparer.Equals(_slots[position].value, item))
{
Position = position;
return true;
}
Position = ulong.MaxValue;
if(add)
{
if(Count >= _slots.Length)
{
var newsize = _hashBuckets.Length * 2;
var newhashebuckets = new BigArray<ulong>(newsize);
var newslots = new BigArray<Slot>(newsize);
for(var i = 0ul; i < newhashebuckets.Length; i++)
newhashebuckets[i] = ulong.MaxValue;
for(var i = 0ul; i < Count; i++)
{
var pos = _slots[i].hashCode % newsize;
newslots[i] = new Slot(_slots[i].hashCode, newhashebuckets[pos], _slots[i].value);
newhashebuckets[pos] = i;
}
_hashBuckets = newhashebuckets;
_slots = newslots;
}
var hashPos = hashCode % _hashBuckets.Length;
var news = new Slot(hashCode, _hashBuckets[hashPos], item);
_slots[Count] = news;
_hashBuckets[hashPos] = Count;
Position = Count;
Count++;
Version++;
}
return false;
}
[Serializable]
internal struct Slot
{
public ulong hashCode;
public ulong next;
public T value;
public Slot(ulong hc, ulong n, T v)
{
hashCode = hc;
next = n;
value = v;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment