replace bitset
							parent
							
								
									05fa578652
								
							
						
					
					
						commit
						d4115b231c
					
				|  | @ -1,33 +0,0 @@ | |||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace Encompass | ||||
| { | ||||
|     internal class BitArrayPool | ||||
|     { | ||||
|         private Stack<BitArray> bitArrays; | ||||
| 
 | ||||
|         public BitArrayPool(int capacity) | ||||
|         { | ||||
|             bitArrays = new Stack<BitArray>(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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -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<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,13 +1,12 @@ | |||
| using Encompass.Collections; | ||||
| using MoonTools.FastCollections; | ||||
| using System; | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace Encompass | ||||
| { | ||||
|     internal class ComponentBitSet | ||||
|     { | ||||
|         Dictionary<int, BitSet> entities = new Dictionary<int, BitSet>(); | ||||
|         Dictionary<int, BitSet512> entities = new Dictionary<int, BitSet512>(); | ||||
|         Dictionary<Type, int> TypeToIndex { get; } | ||||
| 
 | ||||
|         public ComponentBitSet(Dictionary<Type, int> 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<TComponent>(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; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -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); | ||||
|         } | ||||
|  |  | |||
|  | @ -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 | |||
|         /// </summary> | ||||
|         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 | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ | |||
|     <Company>Moonside Games</Company> | ||||
|     <Product>Encompass ECS</Product> | ||||
|     <PackageProjectUrl>https://github.com/encompass-ecs</PackageProjectUrl> | ||||
|     <PackageLicenseUrl/> | ||||
|     <PackageLicenseUrl /> | ||||
|     <Copyright>Evan Hemsley 2019</Copyright> | ||||
|     <Description>Encompass is an engine-agnostic Hyper ECS framework to help you code games, or other kinds of simulations.</Description> | ||||
|     <GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
|  | @ -19,11 +19,12 @@ | |||
|   <ItemGroup> | ||||
|     <None Include="..\LICENSE"> | ||||
|       <Pack>True</Pack> | ||||
|       <PackagePath/> | ||||
|       <PackagePath /> | ||||
|     </None> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <PackageReference Include="MoonTools.Core.Graph" Version="1.0.0"/> | ||||
|     <PackageReference Include="System.Collections.Immutable" Version="1.7.0"/> | ||||
|     <PackageReference Include="MoonTools.Core.Graph" Version="1.0.0" /> | ||||
|     <PackageReference Include="MoonTools.FastCollections" Version="1.0.0" /> | ||||
|     <PackageReference Include="System.Collections.Immutable" Version="1.7.0" /> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
|  | @ -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(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue