From d4115b231cef9e0a1ed01eaccfc4f56a2d05d5bd Mon Sep 17 00:00:00 2001 From: Evan Hemsley <2342303+ehemsley@users.noreply.github.com> Date: Sat, 28 Dec 2019 21:39:35 -0800 Subject: [PATCH] replace bitset --- encompass-cs/Collections/BitArrayPool.cs | 33 ---- encompass-cs/Collections/BitSet.cs | 182 -------------------- encompass-cs/Collections/ComponentBitSet.cs | 11 +- encompass-cs/Collections/ComponentStore.cs | 4 +- encompass-cs/Engine.cs | 20 +-- encompass-cs/EntitySetQuery.cs | 36 ++-- encompass-cs/encompass-cs.csproj | 9 +- test/BitSetTest.cs | 62 ------- 8 files changed, 39 insertions(+), 318 deletions(-) delete mode 100644 encompass-cs/Collections/BitArrayPool.cs delete mode 100644 encompass-cs/Collections/BitSet.cs delete mode 100644 test/BitSetTest.cs diff --git a/encompass-cs/Collections/BitArrayPool.cs b/encompass-cs/Collections/BitArrayPool.cs deleted file mode 100644 index 0f0165f..0000000 --- a/encompass-cs/Collections/BitArrayPool.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections; -using System.Collections.Generic; - -namespace Encompass -{ - internal class BitArrayPool - { - private Stack bitArrays; - - public BitArrayPool(int capacity) - { - bitArrays = new Stack(capacity); - - for (var i = 0; i < capacity; i++) - { - bitArrays.Push(new BitArray(128)); - } - } - - public BitArray Obtain(int size) - { - var bitArray = bitArrays.Pop(); - bitArray.Length = size; - bitArray.SetAll(false); - return bitArray; - } - - public void Free(BitArray bitArray) - { - bitArrays.Push(bitArray); - } - } -} diff --git a/encompass-cs/Collections/BitSet.cs b/encompass-cs/Collections/BitSet.cs deleted file mode 100644 index abe9960..0000000 --- a/encompass-cs/Collections/BitSet.cs +++ /dev/null @@ -1,182 +0,0 @@ -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; - } - } -} diff --git a/encompass-cs/Collections/ComponentBitSet.cs b/encompass-cs/Collections/ComponentBitSet.cs index c85f71f..1d0c39d 100644 --- a/encompass-cs/Collections/ComponentBitSet.cs +++ b/encompass-cs/Collections/ComponentBitSet.cs @@ -1,13 +1,12 @@ -using Encompass.Collections; +using MoonTools.FastCollections; using System; -using System.Collections; using System.Collections.Generic; namespace Encompass { internal class ComponentBitSet { - Dictionary entities = new Dictionary(); + Dictionary entities = new Dictionary(); Dictionary TypeToIndex { get; } public ComponentBitSet(Dictionary typeToIndex) @@ -22,7 +21,7 @@ namespace Encompass public void AddEntity(int entityID) { - entities.Add(entityID, BitSetBuilder.Zeroes()); + entities.Add(entityID, BitSet512.Zero); } public void Set(int entityID) where TComponent : struct, IComponent @@ -47,9 +46,9 @@ namespace Encompass } } - public BitSet EntityBitArray(int entityID) + public BitSet512 EntityBitArray(int entityID) { - return entities.ContainsKey(entityID) ? entities[entityID] : BitSetBuilder.Zeroes(); + return entities.ContainsKey(entityID) ? entities[entityID] : BitSet512.Zero; } } } diff --git a/encompass-cs/Collections/ComponentStore.cs b/encompass-cs/Collections/ComponentStore.cs index 9e6aed6..03904b1 100644 --- a/encompass-cs/Collections/ComponentStore.cs +++ b/encompass-cs/Collections/ComponentStore.cs @@ -1,4 +1,4 @@ -using Encompass.Collections; +using MoonTools.FastCollections; using System; using System.Collections.Generic; @@ -47,7 +47,7 @@ namespace Encompass return Stores.ContainsKey(type) && Stores[type].Has(entityID); } - public BitSet EntityBitArray(int entityID) + public BitSet512 EntityBitArray(int entityID) { return ComponentBitSet.EntityBitArray(entityID); } diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index 58bf6bb..c748cea 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -3,7 +3,7 @@ using System.Reflection; using System.Collections.Generic; using System.Linq; using Encompass.Exceptions; -using Encompass.Collections; +using MoonTools.FastCollections; namespace Encompass { @@ -686,36 +686,36 @@ namespace Encompass /// internal void BuildEntityQuery() { - var withMask = BitSetBuilder.Zeroes(); + var withMask = BitSet512.Zero; foreach (var type in queryWithTypes) { withMask = withMask.Set(componentUpdateManager.TypeToIndex[type]); } - var withoutMask = BitSetBuilder.Zeroes(); + var withoutMask = BitSet512.Zero; foreach (var type in queryWithoutTypes) { withoutMask = withoutMask.Set(componentUpdateManager.TypeToIndex[type]); } - var immediateMask = BitSetBuilder.Zeroes(); + var immediateMask = BitSet512.Zero; foreach (var type in readImmediateTypes) { immediateMask = immediateMask.Set(componentUpdateManager.TypeToIndex[type]); } - var existingMask = BitSetBuilder.Zeroes(); + var existingMask = BitSet512.Zero; foreach (var type in readTypes) { existingMask = existingMask.Set(componentUpdateManager.TypeToIndex[type]); } entityQuery = new EntitySetQuery( - withMask.And(immediateMask), - withMask.And(existingMask), - withoutMask.And(immediateMask), - withoutMask.And(existingMask), - withMask.Not() + withMask & immediateMask, + withMask & existingMask, + withoutMask & immediateMask, + withoutMask & existingMask, + ~withMask ); } diff --git a/encompass-cs/EntitySetQuery.cs b/encompass-cs/EntitySetQuery.cs index 02f903b..04c0432 100644 --- a/encompass-cs/EntitySetQuery.cs +++ b/encompass-cs/EntitySetQuery.cs @@ -1,18 +1,16 @@ -using System.Collections; -using System.Collections.Generic; -using Encompass.Collections; +using MoonTools.FastCollections; namespace Encompass { internal struct EntitySetQuery { - private BitSet WithImmediateMask { get; } - private BitSet WithExistingMask { get; } - private BitSet WithoutImmediateMask { get; } - private BitSet WithoutExistingMask { get; } - private BitSet NotWithMask { get; } + private BitSet512 WithImmediateMask { get; } + private BitSet512 WithExistingMask { get; } + private BitSet512 WithoutImmediateMask { get; } + private BitSet512 WithoutExistingMask { get; } + private BitSet512 NotWithMask { get; } - internal EntitySetQuery(BitSet withImmediateMask, BitSet withExistingMask, BitSet withoutImmediateMask, BitSet withoutExistingMask, BitSet notWithMask) + internal EntitySetQuery(BitSet512 withImmediateMask, BitSet512 withExistingMask, BitSet512 withoutImmediateMask, BitSet512 withoutExistingMask, BitSet512 notWithMask) { WithImmediateMask = withImmediateMask; WithExistingMask = withExistingMask; @@ -24,11 +22,11 @@ namespace Encompass public bool CheckEntity(Entity entity, ComponentBitSet componentBitSet) { var existingBits = componentBitSet.EntityBitArray(entity.ID); - var existing = WithExistingMask.And(existingBits).Or(NotWithMask); + var existing = (WithExistingMask & existingBits) | NotWithMask; - var existingForbidden = WithoutExistingMask.And(existingBits).Not(); + var existingForbidden = ~(WithoutExistingMask & existingBits); - return existing.And(existingForbidden).AllTrue(); + return (existing & existingForbidden).AllTrue(); } public bool ImmediateCheckEntity(Entity entity, ComponentBitSet immediateBitLookup, ComponentBitSet existingBitLookup) @@ -36,15 +34,15 @@ namespace Encompass var immediateBits = immediateBitLookup.EntityBitArray(entity.ID); var existingBits = existingBitLookup.EntityBitArray(entity.ID); - var immediate = WithImmediateMask.And(immediateBits); - var existing = WithExistingMask.And(existingBits); - var withCheck = immediate.Or(existing).Or(NotWithMask); + var immediate = WithImmediateMask & immediateBits; + var existing = WithExistingMask & existingBits; + var withCheck = immediate | existing | NotWithMask; - var immediateForbidden = WithoutImmediateMask.And(immediateBits).Not(); - var existingForbidden = WithoutExistingMask.And(existingBits).Not(); - var withoutCheck = immediateForbidden.And(existingForbidden); + var immediateForbidden = ~(WithoutImmediateMask & immediateBits); + var existingForbidden = ~(WithoutExistingMask & existingBits); + var withoutCheck = immediateForbidden & existingForbidden; - return withCheck.And(withoutCheck).AllTrue(); + return (withCheck & withoutCheck).AllTrue(); } } } diff --git a/encompass-cs/encompass-cs.csproj b/encompass-cs/encompass-cs.csproj index cb51bab..37a5ba2 100644 --- a/encompass-cs/encompass-cs.csproj +++ b/encompass-cs/encompass-cs.csproj @@ -9,7 +9,7 @@ Moonside Games Encompass ECS https://github.com/encompass-ecs - + Evan Hemsley 2019 Encompass is an engine-agnostic Hyper ECS framework to help you code games, or other kinds of simulations. true @@ -19,11 +19,12 @@ True - + - - + + + \ No newline at end of file diff --git a/test/BitSetTest.cs b/test/BitSetTest.cs deleted file mode 100644 index dfcfb6d..0000000 --- a/test/BitSetTest.cs +++ /dev/null @@ -1,62 +0,0 @@ -using Encompass.Collections; -using FluentAssertions; -using NUnit.Framework; - -namespace Tests -{ - public class BitSetTest - { - [Test] - public void Zeroes() - { - var bitSet = BitSetBuilder.Zeroes(); - bitSet.AllFalse().Should().BeTrue(); - } - - [Test] - public void Ones() - { - var bitSet = BitSetBuilder.Ones(); - bitSet.AllTrue().Should().BeTrue(); - } - - [Test] - public void Set() - { - var bitSet = BitSetBuilder.Zeroes().Set(5); - bitSet.AllFalse().Should().BeFalse(); - - bitSet = BitSetBuilder.Zeroes().Set(132); - bitSet.AllFalse().Should().BeFalse(); - - bitSet = BitSetBuilder.Zeroes().Set(268); - bitSet.AllFalse().Should().BeFalse(); - - bitSet = BitSetBuilder.Zeroes().Set(450); - bitSet.AllFalse().Should().BeFalse(); - } - - [Test] - public void UnSet() - { - var bitSet = BitSetBuilder.Ones().UnSet(285); - bitSet.Get(285).Should().BeFalse(); - bitSet.Set(285).AllTrue().Should().BeTrue(); - } - - [Test] - public void Get() - { - var bitSet = BitSetBuilder.Zeroes().Set(359); - bitSet.Get(359).Should().BeTrue(); - bitSet.UnSet(359).AllFalse().Should().BeTrue(); - } - - [Test] - public void Not() - { - var bitSet = BitSetBuilder.Ones().Not(); - bitSet.AllFalse().Should().BeTrue(); - } - } -}