Skip to content

Instantly share code, notes, and snippets.

@paavohuhtala
Last active December 21, 2019 18:12
Show Gist options
  • Save paavohuhtala/f5732220c3b6e39daeb92405d027736f to your computer and use it in GitHub Desktop.
Save paavohuhtala/f5732220c3b6e39daeb92405d027736f to your computer and use it in GitHub Desktop.
[StructLayout(LayoutKind.Sequential)]
public struct BitArray512<TEnum> : IEquatable<BitArray512<TEnum>>
{
private ulong _a0;
private ulong _a1;
private ulong _a2;
private ulong _a3;
private ulong _a4;
private ulong _a5;
private ulong _a6;
private ulong _a7;
private int _setBits;
public static readonly int Length = Enum.GetValues(typeof(TEnum)).Length;
public bool AnyBitSet
{
get => SetBitsCount > 0;
}
public int SetBitsCount
{
get
{
if (_setBits == -1)
{
_setBits = (int) CountSetBits();
}
return _setBits;
}
}
public void Set(int bit, bool value)
{
var byteOffset = bit >> 3; // bit / 8
var bitOffset = bit & 7; // bit % 8
unsafe
{
var pointer = (byte*) Unsafe.AsPointer(ref this);
if (value)
{
*(pointer + byteOffset) |= (byte) (1 << bitOffset);
}
else
{
*(pointer + byteOffset) &= (byte) ~(1 << bitOffset);
}
}
_setBits = -1;
}
public bool Get(int bit)
{
var byteOffset = bit >> 3; // bit / 8
var bitOffset = bit & 7; // bit % 8
unsafe
{
var pointer = (byte*) Unsafe.AsPointer(ref this);
return (*(pointer + byteOffset) & (1 << bitOffset)) > 0;
}
}
public void SetAll(bool value)
{
var byteOffset = 0;
var remainingBits = Length;
unsafe
{
var pointerLong = (ulong*) Unsafe.AsPointer(ref this);
var targetLong = value ? ulong.MaxValue : 0;
while (remainingBits >= 64)
{
*pointerLong = targetLong;
pointerLong++;
byteOffset += 8;
remainingBits -= 64;
}
for (var i = byteOffset; i < remainingBits; i++)
{
Set(i, value);
}
}
if (value)
{
_setBits = Length;
}
else
{
_setBits = 0;
}
}
private int CountSetBits()
{
return BitOperations.PopCount(_a0) +
BitOperations.PopCount(_a1) +
BitOperations.PopCount(_a2) +
BitOperations.PopCount(_a3) +
BitOperations.PopCount(_a4) +
BitOperations.PopCount(_a5) +
BitOperations.PopCount(_a6) +
BitOperations.PopCount(_a7);
}
public BitArray512<TEnum> And(BitArray512<TEnum> other)
{
return new BitArray512<TEnum> {
_a0 = _a0 & other._a0,
_a1 = _a1 & other._a1,
_a2 = _a2 & other._a2,
_a3 = _a3 & other._a3,
_a4 = _a4 & other._a4,
_a5 = _a5 & other._a5,
_a6 = _a6 & other._a6,
_a7 = _a7 & other._a7
};
}
public bool Equals(BitArray512<TEnum> other)
{
return
_a0 == other._a0 &&
_a1 == other._a1 &&
_a2 == other._a2 &&
_a3 == other._a3 &&
_a4 == other._a4 &&
_a5 == other._a5 &&
_a6 == other._a6 &&
_a7 == other._a7;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment