change bitset to be cross platform
parent
51a248156e
commit
b1c09a20a0
|
@ -0,0 +1,182 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace Encompass.Collections
|
||||
{
|
||||
public static class BitSet512Builder
|
||||
{
|
||||
public static BitSet512 Zeroes()
|
||||
{
|
||||
return new BitSet512(Vector128Builder.Zeroes(), Vector128Builder.Zeroes(), Vector128Builder.Zeroes(), Vector128Builder.Zeroes());
|
||||
}
|
||||
|
||||
public static BitSet512 Ones()
|
||||
{
|
||||
return new BitSet512(Vector128Builder.Ones(), Vector128Builder.Ones(), Vector128Builder.Ones(), Vector128Builder.Ones());
|
||||
}
|
||||
}
|
||||
|
||||
public static class Vector128Builder
|
||||
{
|
||||
static readonly uint[] zeroes = new uint[4]; // max size of a Vector<T> is 8 uints
|
||||
static readonly uint[] ones = new uint[4] { uint.MaxValue, uint.MaxValue, uint.MaxValue, uint.MaxValue };
|
||||
static uint[] builderInts = new uint[4];
|
||||
|
||||
private static void ResetBuilder()
|
||||
{
|
||||
for (var i = 0; i < 4; 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 > 127) { throw new System.ArgumentOutOfRangeException(nameof(index)); }
|
||||
ResetBuilder();
|
||||
builderInts[index / 32] |= (uint)(1 << (index % 32));
|
||||
return new Vector<uint>(builderInts);
|
||||
}
|
||||
}
|
||||
|
||||
public struct BitSet512
|
||||
{
|
||||
public Vector<uint> A { get; }
|
||||
public Vector<uint> B { get; }
|
||||
public Vector<uint> C { get; }
|
||||
public Vector<uint> D { get; }
|
||||
|
||||
internal BitSet512(Vector<uint> a, Vector<uint> b, Vector<uint> c, Vector<uint> d)
|
||||
{
|
||||
A = a;
|
||||
B = b;
|
||||
C = c;
|
||||
D = d;
|
||||
}
|
||||
|
||||
public BitSet512 And(BitSet512 other)
|
||||
{
|
||||
return new BitSet512(A & other.A, B & other.B, C & other.C, D & other.D);
|
||||
}
|
||||
|
||||
public BitSet512 Or(BitSet512 other)
|
||||
{
|
||||
return new BitSet512(A | other.A, B | other.B, C | other.C, D | other.D);
|
||||
}
|
||||
|
||||
public BitSet512 Not()
|
||||
{
|
||||
return new BitSet512(~A, ~B, ~C, ~D);
|
||||
}
|
||||
|
||||
public BitSet512 Set(int index)
|
||||
{
|
||||
if (index < 128)
|
||||
{
|
||||
return new BitSet512(A | Vector128Builder.Build(index % 128), B, C, D);
|
||||
}
|
||||
else if (index < 256)
|
||||
{
|
||||
return new BitSet512(A, B | Vector128Builder.Build(index % 128), C, D);
|
||||
}
|
||||
else if (index < 384)
|
||||
{
|
||||
return new BitSet512(A, B, C | Vector128Builder.Build(index % 128), D);
|
||||
}
|
||||
else if (index < 512)
|
||||
{
|
||||
return new BitSet512(A, B, C, D | Vector128Builder.Build(index % 128));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
}
|
||||
|
||||
public BitSet512 UnSet(int index)
|
||||
{
|
||||
if (index < 128)
|
||||
{
|
||||
return new BitSet512(A & ~Vector128Builder.Build(index % 128), B, C, D);
|
||||
}
|
||||
else if (index < 256)
|
||||
{
|
||||
return new BitSet512(A, B & ~Vector128Builder.Build(index % 128), C, D);
|
||||
}
|
||||
else if (index < 384)
|
||||
{
|
||||
return new BitSet512(A, B, C & ~Vector128Builder.Build(index % 128), D);
|
||||
}
|
||||
else if (index < 512)
|
||||
{
|
||||
return new BitSet512(A, B, C, D & ~Vector128Builder.Build(index % 128));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
}
|
||||
|
||||
public bool Get(int index)
|
||||
{
|
||||
var vectorIndex = index % 128;
|
||||
if (index < 128)
|
||||
{
|
||||
return (A[vectorIndex / 32] & (uint)(1 << vectorIndex % 32)) != 0;
|
||||
}
|
||||
else if (index < 256)
|
||||
{
|
||||
return (B[vectorIndex / 32] & (uint)(1 << vectorIndex % 32)) != 0;
|
||||
}
|
||||
else if (index < 384)
|
||||
{
|
||||
return (C[vectorIndex / 32] & (uint)(1 << vectorIndex % 32)) != 0;
|
||||
}
|
||||
else if (index < 512)
|
||||
{
|
||||
return (D[vectorIndex / 32] & (uint)(1 << vectorIndex % 32)) != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
}
|
||||
|
||||
public bool AllTrue()
|
||||
{
|
||||
for (var i = 0; i < 4; 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 < 4; 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ namespace Encompass
|
|||
{
|
||||
internal class ComponentBitSet
|
||||
{
|
||||
Dictionary<Entity, BitSet512> entities = new Dictionary<Entity, BitSet512>();
|
||||
Dictionary<Entity, BitSet> entities = new Dictionary<Entity, BitSet>();
|
||||
Dictionary<Type, int> TypeToIndex { get; }
|
||||
|
||||
public ComponentBitSet(Dictionary<Type, int> typeToIndex)
|
||||
|
@ -27,7 +27,7 @@ namespace Encompass
|
|||
|
||||
public void AddEntity(Entity entity)
|
||||
{
|
||||
entities.Add(entity, BitSet512Builder.Zeroes());
|
||||
entities.Add(entity, BitSetBuilder.Zeroes());
|
||||
}
|
||||
|
||||
public void Set<TComponent>(Entity entity) where TComponent : struct, IComponent
|
||||
|
@ -52,9 +52,9 @@ namespace Encompass
|
|||
}
|
||||
}
|
||||
|
||||
public BitSet512 EntityBitArray(Entity entity)
|
||||
public BitSet EntityBitArray(Entity entity)
|
||||
{
|
||||
return entities.ContainsKey(entity) ? entities[entity] : BitSet512Builder.Zeroes();
|
||||
return entities.ContainsKey(entity) ? entities[entity] : BitSetBuilder.Zeroes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace Encompass
|
|||
return Stores.ContainsKey(type) && Stores[type].Has(entity);
|
||||
}
|
||||
|
||||
public BitSet512 EntityBitArray(Entity entity)
|
||||
public BitSet EntityBitArray(Entity entity)
|
||||
{
|
||||
return ComponentBitSet.EntityBitArray(entity);
|
||||
}
|
||||
|
|
|
@ -642,25 +642,25 @@ namespace Encompass
|
|||
/// </summary>
|
||||
internal void BuildEntityQuery()
|
||||
{
|
||||
var withMask = BitSet512Builder.Zeroes();
|
||||
var withMask = BitSetBuilder.Zeroes();
|
||||
foreach (var type in queryWithTypes)
|
||||
{
|
||||
withMask = withMask.Set(componentUpdateManager.TypeToIndex[type]);
|
||||
}
|
||||
|
||||
var withoutMask = BitSet512Builder.Zeroes();
|
||||
var withoutMask = BitSetBuilder.Zeroes();
|
||||
foreach (var type in queryWithoutTypes)
|
||||
{
|
||||
withoutMask = withoutMask.Set(componentUpdateManager.TypeToIndex[type]);
|
||||
}
|
||||
|
||||
var pendingMask = BitSet512Builder.Zeroes();
|
||||
var pendingMask = BitSetBuilder.Zeroes();
|
||||
foreach (var type in readPendingTypes)
|
||||
{
|
||||
pendingMask = pendingMask.Set(componentUpdateManager.TypeToIndex[type]);
|
||||
}
|
||||
|
||||
var existingMask = BitSet512Builder.Zeroes();
|
||||
var existingMask = BitSetBuilder.Zeroes();
|
||||
foreach (var type in readTypes)
|
||||
{
|
||||
existingMask = existingMask.Set(componentUpdateManager.TypeToIndex[type]);
|
||||
|
|
|
@ -6,13 +6,13 @@ namespace Encompass
|
|||
{
|
||||
internal struct EntitySetQuery
|
||||
{
|
||||
private BitSet512 WithPendingMask { get; }
|
||||
private BitSet512 WithExistingMask { get; }
|
||||
private BitSet512 WithoutPendingMask { get; }
|
||||
private BitSet512 WithoutExistingMask { get; }
|
||||
private BitSet512 NotWithMask { get; }
|
||||
private BitSet WithPendingMask { get; }
|
||||
private BitSet WithExistingMask { get; }
|
||||
private BitSet WithoutPendingMask { get; }
|
||||
private BitSet WithoutExistingMask { get; }
|
||||
private BitSet NotWithMask { get; }
|
||||
|
||||
internal EntitySetQuery(BitSet512 withPendingMask, BitSet512 withExistingMask, BitSet512 withoutPendingMask, BitSet512 withoutExistingMask, BitSet512 notWithMask)
|
||||
internal EntitySetQuery(BitSet withPendingMask, BitSet withExistingMask, BitSet withoutPendingMask, BitSet withoutExistingMask, BitSet notWithMask)
|
||||
{
|
||||
WithPendingMask = withPendingMask;
|
||||
WithExistingMask = withExistingMask;
|
||||
|
|
|
@ -4,42 +4,42 @@ using NUnit.Framework;
|
|||
|
||||
namespace Tests
|
||||
{
|
||||
public class BitSet512Test
|
||||
public class BitSetTest
|
||||
{
|
||||
[Test]
|
||||
public void Zeroes()
|
||||
{
|
||||
var bitSet = BitSet512Builder.Zeroes();
|
||||
var bitSet = BitSetBuilder.Zeroes();
|
||||
bitSet.AllFalse().Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Ones()
|
||||
{
|
||||
var bitSet = BitSet512Builder.Ones();
|
||||
var bitSet = BitSetBuilder.Ones();
|
||||
bitSet.AllTrue().Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Set()
|
||||
{
|
||||
var bitSet = BitSet512Builder.Zeroes().Set(5);
|
||||
var bitSet = BitSetBuilder.Zeroes().Set(5);
|
||||
bitSet.AllFalse().Should().BeFalse();
|
||||
|
||||
bitSet = BitSet512Builder.Zeroes().Set(132);
|
||||
bitSet = BitSetBuilder.Zeroes().Set(132);
|
||||
bitSet.AllFalse().Should().BeFalse();
|
||||
|
||||
bitSet = BitSet512Builder.Zeroes().Set(268);
|
||||
bitSet = BitSetBuilder.Zeroes().Set(268);
|
||||
bitSet.AllFalse().Should().BeFalse();
|
||||
|
||||
bitSet = BitSet512Builder.Zeroes().Set(450);
|
||||
bitSet = BitSetBuilder.Zeroes().Set(450);
|
||||
bitSet.AllFalse().Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnSet()
|
||||
{
|
||||
var bitSet = BitSet512Builder.Ones().UnSet(285);
|
||||
var bitSet = BitSetBuilder.Ones().UnSet(285);
|
||||
bitSet.Get(285).Should().BeFalse();
|
||||
bitSet.Set(285).AllTrue().Should().BeTrue();
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ namespace Tests
|
|||
[Test]
|
||||
public void Get()
|
||||
{
|
||||
var bitSet = BitSet512Builder.Zeroes().Set(359);
|
||||
var bitSet = BitSetBuilder.Zeroes().Set(359);
|
||||
bitSet.Get(359).Should().BeTrue();
|
||||
bitSet.UnSet(359).AllFalse().Should().BeTrue();
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ namespace Tests
|
|||
[Test]
|
||||
public void Not()
|
||||
{
|
||||
var bitSet = BitSet512Builder.Ones().Not();
|
||||
var bitSet = BitSetBuilder.Ones().Not();
|
||||
bitSet.AllFalse().Should().BeTrue();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue