encompass-cs/encompass-cs/Collections/BitSet.cs

183 lines
5.6 KiB
C#

using System.Collections.Generic;
using System.Linq;
using System.Numerics;
namespace Encompass.Collections
{
public static class BitSetBuilder
{
public static BitSet Zeroes()
{
return new BitSet(VectorBuilder.Zeroes(), VectorBuilder.Zeroes(), VectorBuilder.Zeroes(), VectorBuilder.Zeroes());
}
public static BitSet Ones()
{
return new BitSet(VectorBuilder.Ones(), VectorBuilder.Ones(), VectorBuilder.Ones(), VectorBuilder.Ones());
}
}
public static class VectorBuilder
{
static readonly uint[] zeroes = new uint[Vector<uint>.Count]; // max size of a Vector<T> is 8 uints
static readonly uint[] ones = Enumerable.Repeat(uint.MaxValue, Vector<uint>.Count).ToArray();
static uint[] builderInts = new uint[Vector<uint>.Count];
private static void ResetBuilder()
{
for (var i = 0; i < Vector<uint>.Count; i++)
{
builderInts[i] = 0;
}
}
public static Vector<uint> Zeroes()
{
return new Vector<uint>(zeroes);
}
public static Vector<uint> Ones()
{
return new Vector<uint>(ones);
}
public static Vector<uint> Build(int index)
{
if (index > Vector<uint>.Count * 32) { throw new System.ArgumentOutOfRangeException(nameof(index)); }
ResetBuilder();
builderInts[index / 32] |= (uint)(1 << (index % 32));
return new Vector<uint>(builderInts);
}
}
public struct BitSet
{
public static int VectorLength { get { return Vector<uint>.Count * 32; } }
public Vector<uint> A { get; }
public Vector<uint> B { get; }
public Vector<uint> C { get; }
public Vector<uint> D { get; }
internal BitSet(Vector<uint> a, Vector<uint> b, Vector<uint> c, Vector<uint> d)
{
A = a;
B = b;
C = c;
D = d;
}
public BitSet And(BitSet other)
{
return new BitSet(A & other.A, B & other.B, C & other.C, D & other.D);
}
public BitSet Or(BitSet other)
{
return new BitSet(A | other.A, B | other.B, C | other.C, D | other.D);
}
public BitSet Not()
{
return new BitSet(~A, ~B, ~C, ~D);
}
public BitSet Set(int index)
{
if (index < VectorLength)
{
return new BitSet(A | VectorBuilder.Build(index % VectorLength), B, C, D);
}
else if (index < VectorLength * 2)
{
return new BitSet(A, B | VectorBuilder.Build(index % VectorLength), C, D);
}
else if (index < VectorLength * 3)
{
return new BitSet(A, B, C | VectorBuilder.Build(index % VectorLength), D);
}
else if (index < VectorLength * 4)
{
return new BitSet(A, B, C, D | VectorBuilder.Build(index % VectorLength));
}
else
{
throw new System.ArgumentOutOfRangeException(nameof(index));
}
}
public BitSet UnSet(int index)
{
if (index < VectorLength)
{
return new BitSet(A & ~VectorBuilder.Build(index % VectorLength), B, C, D);
}
else if (index < VectorLength * 2)
{
return new BitSet(A, B & ~VectorBuilder.Build(index % VectorLength), C, D);
}
else if (index < VectorLength * 3)
{
return new BitSet(A, B, C & ~VectorBuilder.Build(index % VectorLength), D);
}
else if (index < VectorLength * 4)
{
return new BitSet(A, B, C, D & ~VectorBuilder.Build(index % VectorLength));
}
else
{
throw new System.ArgumentOutOfRangeException(nameof(index));
}
}
public bool Get(int index)
{
var vectorIndex = index % VectorLength;
if (index < VectorLength)
{
return (A[vectorIndex / 32] & (uint)(1 << vectorIndex % 32)) != 0;
}
else if (index < VectorLength * 2)
{
return (B[vectorIndex / 32] & (uint)(1 << vectorIndex % 32)) != 0;
}
else if (index < VectorLength * 3)
{
return (C[vectorIndex / 32] & (uint)(1 << vectorIndex % 32)) != 0;
}
else if (index < VectorLength * 4)
{
return (D[vectorIndex / 32] & (uint)(1 << vectorIndex % 32)) != 0;
}
else
{
throw new System.ArgumentOutOfRangeException(nameof(index));
}
}
public bool AllTrue()
{
for (var i = 0; i < Vector<uint>.Count; i++)
{
if (A[i] != uint.MaxValue) { return false; }
if (B[i] != uint.MaxValue) { return false; }
if (C[i] != uint.MaxValue) { return false; }
if (D[i] != uint.MaxValue) { return false; }
}
return true;
}
public bool AllFalse()
{
for (var i = 0; i < Vector<uint>.Count; i++)
{
if (A[i] != 0) { return false; }
if (B[i] != 0) { return false; }
if (C[i] != 0) { return false; }
if (D[i] != 0) { return false; }
}
return true;
}
}
}