diff options
Diffstat (limited to 'ARMeilleure/Common/BitMap.cs')
| -rw-r--r-- | ARMeilleure/Common/BitMap.cs | 87 |
1 files changed, 67 insertions, 20 deletions
diff --git a/ARMeilleure/Common/BitMap.cs b/ARMeilleure/Common/BitMap.cs index 9dff271b..35100536 100644 --- a/ARMeilleure/Common/BitMap.cs +++ b/ARMeilleure/Common/BitMap.cs @@ -1,20 +1,50 @@ using System.Collections; using System.Collections.Generic; +using System.Numerics; namespace ARMeilleure.Common { - class BitMap : IEnumerable<int> + class BitMap : IEnumerator<int> { - private const int IntSize = 32; + private const int IntSize = 64; private const int IntMask = IntSize - 1; - private List<int> _masks; + private List<long> _masks; + + private int _enumIndex; + private long _enumMask; + private int _enumBit; + + public int Current => _enumIndex * IntSize + _enumBit; + object IEnumerator.Current => Current; + + public BitMap() + { + _masks = new List<long>(0); + } public BitMap(int initialCapacity) { int count = (initialCapacity + IntMask) / IntSize; - _masks = new List<int>(count); + _masks = new List<long>(count); + + while (count-- > 0) + { + _masks.Add(0); + } + } + + public void Reset(int initialCapacity) + { + int count = (initialCapacity + IntMask) / IntSize; + + if (count > _masks.Capacity) + { + _masks.Capacity = count; + } + + _masks.Clear(); while (count-- > 0) { @@ -29,7 +59,7 @@ namespace ARMeilleure.Common int wordIndex = bit / IntSize; int wordBit = bit & IntMask; - int wordMask = 1 << wordBit; + long wordMask = 1L << wordBit; if ((_masks[wordIndex] & wordMask) != 0) { @@ -48,7 +78,7 @@ namespace ARMeilleure.Common int wordIndex = bit / IntSize; int wordBit = bit & IntMask; - int wordMask = 1 << wordBit; + long wordMask = 1L << wordBit; _masks[wordIndex] &= ~wordMask; } @@ -60,7 +90,7 @@ namespace ARMeilleure.Common int wordIndex = bit / IntSize; int wordBit = bit & IntMask; - return (_masks[wordIndex] & (1 << wordBit)) != 0; + return (_masks[wordIndex] & (1L << wordBit)) != 0; } public bool Set(BitMap map) @@ -71,7 +101,7 @@ namespace ARMeilleure.Common for (int index = 0; index < _masks.Count; index++) { - int newValue = _masks[index] | map._masks[index]; + long newValue = _masks[index] | map._masks[index]; if (_masks[index] != newValue) { @@ -92,7 +122,7 @@ namespace ARMeilleure.Common for (int index = 0; index < _masks.Count; index++) { - int newValue = _masks[index] & ~map._masks[index]; + long newValue = _masks[index] & ~map._masks[index]; if (_masks[index] != newValue) { @@ -105,6 +135,10 @@ namespace ARMeilleure.Common return modified; } + #region IEnumerable<long> Methods + + // Note: The bit enumerator is embedded in this class to avoid creating garbage when enumerating. + private void EnsureCapacity(int size) { while (_masks.Count * IntSize < size) @@ -115,24 +149,37 @@ namespace ARMeilleure.Common public IEnumerator<int> GetEnumerator() { - for (int index = 0; index < _masks.Count; index++) - { - int mask = _masks[index]; + Reset(); + return this; + } - while (mask != 0) + public bool MoveNext() + { + if (_enumMask != 0) + { + _enumMask &= ~(1L << _enumBit); + } + while (_enumMask == 0) + { + if (++_enumIndex >= _masks.Count) { - int bit = BitUtils.LowestBitSet(mask); - - mask &= ~(1 << bit); - - yield return index * IntSize + bit; + return false; } + _enumMask = _masks[_enumIndex]; } + _enumBit = BitOperations.TrailingZeroCount(_enumMask); + return true; } - IEnumerator IEnumerable.GetEnumerator() + public void Reset() { - return GetEnumerator(); + _enumIndex = -1; + _enumMask = 0; + _enumBit = 0; } + + public void Dispose() { } + +#endregion } }
\ No newline at end of file |
