mirror of
https://github.com/Campofinale/CampofinaleBackup.git
synced 2025-12-16 18:14:35 +00:00
190 lines
4.6 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|