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.Count]; // max size of a Vector is 8 uints static readonly uint[] ones = Enumerable.Repeat(uint.MaxValue, Vector.Count).ToArray(); static uint[] builderInts = new uint[Vector.Count]; private static void ResetBuilder() { for (var i = 0; i < Vector.Count; i++) { builderInts[i] = 0; } } public static Vector Zeroes() { return new Vector(zeroes); } public static Vector Ones() { return new Vector(ones); } public static Vector Build(int index) { if (index > Vector.Count * 32) { throw new System.ArgumentOutOfRangeException(nameof(index)); } ResetBuilder(); builderInts[index / 32] |= (uint)(1 << (index % 32)); return new Vector(builderInts); } } public struct BitSet { public static int VectorLength { get { return Vector.Count * 32; } } public Vector A { get; } public Vector B { get; } public Vector C { get; } public Vector D { get; } internal BitSet(Vector a, Vector b, Vector c, Vector 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.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.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; } } }