Campofinale/Campofinale/Resource/LongBitSet.cs
2025-05-16 22:53:22 +02:00

190 lines
4.6 KiB
C#

namespace Campofinale.Resource
{
/// <summary>
/// Utility class for supporting long bit set
/// </summary>
public class LongBitSet
{
ulong[] bits;
int bitCount;
public ulong[] Bits => bits;
public int BitCount => bitCount;
public LongBitSet(int bitCount)
{
InitializeWithBitCount(bitCount);
}
void InitializeWithBitCount(int bitCount)
{
this.bitCount = bitCount;
int cnt = (bitCount / 64);
if (bitCount % 64 != 0)
cnt += 1;
bits = new ulong[cnt];
}
public LongBitSet(ICollection<int> values)
{
int max = 0;
if (values.Count > 0)
{
max = values.Max();
}
InitializeWithBitCount(max);
try
{
foreach (var i in values)
{
SetBit(i, true);
}
}
catch (Exception ex)
{
}
}
public LongBitSet(ulong[] bits)
{
this.bits = bits;
this.bitCount = bits.Length * 64;
}
public bool this[int bit]
{
get
{
return IsBitSet(bit);
}
set
{
SetBit(bit, value);
}
}
public void SetBit(int bit, bool val)
{
if (bit > bitCount)
throw new IndexOutOfRangeException();
int remaining = bit % 64;
int idx = bit / 64;
ref ulong mask = ref bits[idx];
if (val)
{
mask |= ((ulong)1 << remaining);
}
else
{
mask &= ~((ulong)1 << remaining);
}
}
public bool IsBitSet(int bit)
{
if (bit > bitCount)
throw new IndexOutOfRangeException();
int remaining = bit % 64;
int idx = bit / 64;
ulong mask = bits[idx];
ulong test = (ulong)1 << remaining;
return (mask & test) == test;
}
public void And(LongBitSet other)
{
int cnt = Math.Min(bits.Length, other.bits.Length);
for (int i = 0; i < cnt; i++)
{
bits[i] &= other.bits[i];
}
}
public void Or(LongBitSet other)
{
int cnt = Math.Min(bits.Length, other.bits.Length);
for (int i = 0; i < cnt; i++)
{
bits[i] |= other.bits[i];
}
}
public void ClearBits(LongBitSet other)
{
int cnt = Math.Min(bits.Length, other.bits.Length);
for (int i = 0; i < cnt; i++)
{
bits[i] &= ~other.bits[i];
}
}
public int CountTrueBits()
{
int cnt = bitCount;
int res = 0;
for (int i = 0; i < cnt; i++)
{
if (IsBitSet(i))
res++;
}
return res;
}
public void Clear()
{
int cnt = bits.Length;
for (int i = 0; i < cnt; i++)
{
bits[i] = 0;
}
}
public void ConvertToIntValues(List<int> values)
{
for (int i = 0; i < bitCount; i++)
{
if (IsBitSet(i))
values.Add(i);
}
}
public List<int> ConvertToIntValues()
{
List<int> values=new();
for (int i = 0; i < bitCount; i++)
{
if (IsBitSet(i))
values.Add(i);
}
return values;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public override bool Equals(object obj)
{
LongBitSet other = obj as LongBitSet;
if (other != null)
{
if (bitCount == other.bitCount)
{
var cnt = bits.Length;
for (int i = 0; i < cnt; i++)
{
if (bits[i] != other.bits[i])
return false;
}
return true;
}
else
return false;
}
else
return false;
}
}
}