From 63a4a304c8dd377188fb59e3add017a798cb9982 Mon Sep 17 00:00:00 2001 From: Evan Hemsley <2342303+ehemsley@users.noreply.github.com> Date: Sat, 28 Dec 2019 20:40:44 -0800 Subject: [PATCH] initial commit --- .gitignore | 135 +++++++++++++++++++++++++++ MoonTools.FastCollections.sln | 51 ++++++++++ src/BitSet512.cs | 124 ++++++++++++++++++++++++ src/MoonTools.FastCollections.csproj | 17 ++++ test/BitSet512Test.cs | 67 +++++++++++++ test/test.csproj | 20 ++++ 6 files changed, 414 insertions(+) create mode 100644 .gitignore create mode 100644 MoonTools.FastCollections.sln create mode 100644 src/BitSet512.cs create mode 100644 src/MoonTools.FastCollections.csproj create mode 100644 test/BitSet512Test.cs create mode 100644 test/test.csproj diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..976300b --- /dev/null +++ b/.gitignore @@ -0,0 +1,135 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates +.vs/ + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.svclog +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml +*.azurePubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +packages/ +## TODO: If the tool you use requires repositories.config, also uncomment the next line +!packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +![Ss]tyle[Cc]op.targets +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml + +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store + +_NCrunch* + diff --git a/MoonTools.FastCollections.sln b/MoonTools.FastCollections.sln new file mode 100644 index 0000000..9de2f73 --- /dev/null +++ b/MoonTools.FastCollections.sln @@ -0,0 +1,51 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29613.14 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MoonTools.FastCollections", "src\MoonTools.FastCollections.csproj", "{A6BAA858-20B5-4274-A216-7E71990DAAFB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "test", "test\test.csproj", "{26DDCFFB-B3AE-4CB4-8671-ABB15862193F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A6BAA858-20B5-4274-A216-7E71990DAAFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A6BAA858-20B5-4274-A216-7E71990DAAFB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A6BAA858-20B5-4274-A216-7E71990DAAFB}.Debug|x64.ActiveCfg = Debug|Any CPU + {A6BAA858-20B5-4274-A216-7E71990DAAFB}.Debug|x64.Build.0 = Debug|Any CPU + {A6BAA858-20B5-4274-A216-7E71990DAAFB}.Debug|x86.ActiveCfg = Debug|Any CPU + {A6BAA858-20B5-4274-A216-7E71990DAAFB}.Debug|x86.Build.0 = Debug|Any CPU + {A6BAA858-20B5-4274-A216-7E71990DAAFB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A6BAA858-20B5-4274-A216-7E71990DAAFB}.Release|Any CPU.Build.0 = Release|Any CPU + {A6BAA858-20B5-4274-A216-7E71990DAAFB}.Release|x64.ActiveCfg = Release|Any CPU + {A6BAA858-20B5-4274-A216-7E71990DAAFB}.Release|x64.Build.0 = Release|Any CPU + {A6BAA858-20B5-4274-A216-7E71990DAAFB}.Release|x86.ActiveCfg = Release|Any CPU + {A6BAA858-20B5-4274-A216-7E71990DAAFB}.Release|x86.Build.0 = Release|Any CPU + {26DDCFFB-B3AE-4CB4-8671-ABB15862193F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {26DDCFFB-B3AE-4CB4-8671-ABB15862193F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {26DDCFFB-B3AE-4CB4-8671-ABB15862193F}.Debug|x64.ActiveCfg = Debug|Any CPU + {26DDCFFB-B3AE-4CB4-8671-ABB15862193F}.Debug|x64.Build.0 = Debug|Any CPU + {26DDCFFB-B3AE-4CB4-8671-ABB15862193F}.Debug|x86.ActiveCfg = Debug|Any CPU + {26DDCFFB-B3AE-4CB4-8671-ABB15862193F}.Debug|x86.Build.0 = Debug|Any CPU + {26DDCFFB-B3AE-4CB4-8671-ABB15862193F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {26DDCFFB-B3AE-4CB4-8671-ABB15862193F}.Release|Any CPU.Build.0 = Release|Any CPU + {26DDCFFB-B3AE-4CB4-8671-ABB15862193F}.Release|x64.ActiveCfg = Release|Any CPU + {26DDCFFB-B3AE-4CB4-8671-ABB15862193F}.Release|x64.Build.0 = Release|Any CPU + {26DDCFFB-B3AE-4CB4-8671-ABB15862193F}.Release|x86.ActiveCfg = Release|Any CPU + {26DDCFFB-B3AE-4CB4-8671-ABB15862193F}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {085A69AB-C816-491D-B59C-E8533E7F355D} + EndGlobalSection +EndGlobal diff --git a/src/BitSet512.cs b/src/BitSet512.cs new file mode 100644 index 0000000..1fc27f4 --- /dev/null +++ b/src/BitSet512.cs @@ -0,0 +1,124 @@ +namespace MoonTools.FastCollections +{ + public static unsafe class MemoryHelper + { + public static void Copy(uint* src, uint* dest, int count) + { + for (; count != 0; count--) *dest++ = *src++; + } + + public static void Fill(uint* p, int count, uint value) + { + for (; count != 0; count--) *p++ = value; + } + + public static void And(uint* p, uint* q, uint* result, int count) + { + for (; count != 0; count--) *result++ = *p++ & *q++; + } + + public static void Or(uint* p, uint* q, uint* result, int count) + { + for (; count != 0; count--) *result++ = *p++ | *q++; + } + + public static void Not(uint* p, uint* result, int count) + { + for (; count != 0; count--) *result++ = ~*p++; + } + + public static bool Equal(uint* p, uint* q, int count) + { + for (; count != 0; count--) if (*p++ != *q++) { return false; } + return true; + } + + public static bool NotEqual(uint* p, uint* q, int count) + { + for (; count != 0; count--) if (*p++ == *q++) { return false; } + return true; + } + } + + public unsafe struct BitSet512 + { + public static BitSet512 Zero { get; } = new BitSet512(0); + public static BitSet512 Ones { get; } = new BitSet512(uint.MaxValue); + + private const int _uintLength = 16; + + private fixed uint _buffer[_uintLength]; + + public BitSet512(uint value) + { + fixed (uint* p = _buffer) MemoryHelper.Fill(p, _uintLength, value); + } + + public BitSet512(uint* src) + { + fixed (uint* dest = _buffer) MemoryHelper.Copy(src, dest, _uintLength); + } + + public static BitSet512 operator &(BitSet512 a, BitSet512 b) + { + var tmp = stackalloc uint[_uintLength]; + MemoryHelper.And(a._buffer, b._buffer, tmp, _uintLength); + return new BitSet512(tmp); + } + + public static BitSet512 operator |(BitSet512 a, BitSet512 b) + { + var tmp = stackalloc uint[_uintLength]; + MemoryHelper.Or(a._buffer, b._buffer, tmp, _uintLength); + return new BitSet512(tmp); + } + + public static BitSet512 operator ~(BitSet512 a) + { + var tmp = stackalloc uint[_uintLength]; + MemoryHelper.Not(a._buffer, tmp, _uintLength); + return new BitSet512(tmp); + } + + public BitSet512 Set(int index) + { + var tmp = stackalloc uint[_uintLength]; + fixed (uint* p = _buffer) MemoryHelper.Copy(p, tmp, _uintLength); + tmp[index / 32] |= (uint)(1 << index % 32); + return new BitSet512(tmp); + } + + public BitSet512 UnSet(int index) + { + var tmp = stackalloc uint[_uintLength]; + fixed (uint* p = _buffer) MemoryHelper.Copy(p, tmp, _uintLength); + tmp[index / 32] &= ~(uint)(1 << index % 32); + return new BitSet512(tmp); + } + + public bool Get(int bitIndex) + { + uint thing = _buffer[bitIndex / 32]; + return (_buffer[bitIndex / 32] & (uint)(1 << bitIndex % 32)) == _buffer[bitIndex / 32]; + } + + public bool AllTrue() + { + var tmp = stackalloc uint[_uintLength]; + MemoryHelper.Fill(tmp, _uintLength, uint.MaxValue); + fixed (uint* p = _buffer) return MemoryHelper.Equal(p, tmp, _uintLength); + } + + public bool AllFalse() + { + var tmp = stackalloc uint[_uintLength]; + MemoryHelper.Fill(tmp, _uintLength, 0); + fixed (uint* p = _buffer) return MemoryHelper.Equal(p, tmp, _uintLength); + } + + public static BitSet512 BitwiseAnd(BitSet512 left, BitSet512 right) + { + return left & right; + } + } +} diff --git a/src/MoonTools.FastCollections.csproj b/src/MoonTools.FastCollections.csproj new file mode 100644 index 0000000..69f61f9 --- /dev/null +++ b/src/MoonTools.FastCollections.csproj @@ -0,0 +1,17 @@ + + + + netstandard2.0 + true + MoonTools.Collections + MoonTools.Collections + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/test/BitSet512Test.cs b/test/BitSet512Test.cs new file mode 100644 index 0000000..b278564 --- /dev/null +++ b/test/BitSet512Test.cs @@ -0,0 +1,67 @@ +using NUnit.Framework; +using FluentAssertions; + +namespace MoonTools.FastCollections.Test +{ + public class BitSet512Test + { + [Test] + public void Zero() + { + var bitSet = BitSet512.Zero; + bitSet.AllFalse().Should().BeTrue(); + bitSet.AllTrue().Should().BeFalse(); + } + + [Test] + public void Ones() + { + var bitSet = BitSet512.Ones; + bitSet.AllTrue().Should().BeTrue(); + bitSet.AllFalse().Should().BeFalse(); + } + + [Test] + public void Set() + { + var bitSet = BitSet512.Zero.Set(5); + bitSet.Get(5).Should().BeTrue(); + bitSet.AllFalse().Should().BeFalse(); + + bitSet = BitSet512.Zero.Set(132); + bitSet.Get(132).Should().BeTrue(); + bitSet.AllFalse().Should().BeFalse(); + + bitSet = BitSet512.Zero.Set(268); + bitSet.Get(268).Should().BeTrue(); + bitSet.AllFalse().Should().BeFalse(); + + bitSet = BitSet512.Zero.Set(450); + bitSet.Get(450).Should().BeTrue(); + bitSet.AllFalse().Should().BeFalse(); + } + + [Test] + public void UnSet() + { + var bitSet = BitSet512.Ones.UnSet(285); + bitSet.Get(285).Should().BeFalse(); + bitSet.Set(285).AllTrue().Should().BeTrue(); + } + + [Test] + public void Get() + { + var bitSet = BitSet512.Zero.Set(359); + bitSet.Get(359).Should().BeTrue(); + bitSet.UnSet(359).AllFalse().Should().BeTrue(); + } + + [Test] + public void Not() + { + var bitSet = ~BitSet512.Ones; + bitSet.AllFalse().Should().BeTrue(); + } + } +} \ No newline at end of file diff --git a/test/test.csproj b/test/test.csproj new file mode 100644 index 0000000..2a7d93d --- /dev/null +++ b/test/test.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp3.1 + + false + + + + + + + + + + + + + +