public void IterationTest() { const int bitSetSize = 1000; const int sampleSize = bitSetSize / 10; var set = new SparseBitSet(bitSetSize); // Generate random but unique bit numbers: var bitnums = Enumerable.Range(0, set.Length).ReservoirSample(sampleSize); foreach (int i in bitnums) { set.Set(i); } Assert.Equal(100, set.Cardinality); // Retrieve ids in ascending order: var actual = new List <int>(); int id = -1; while ((id = set.NextSetBit(id + 1)) >= 0) { actual.Add(id); } var expected = bitnums.ToList(); expected.Sort((a, b) => a.CompareTo(b)); Assert.Equal(expected, actual); }
void FloodFill(Player p, ushort x, ushort y, ushort z, byte oldType, byte oldExtType, DrawMode fillType, SparseBitSet bits, List <int> buffer, List <int> origins, int depth) { if (bits.Get(x, y, z) || buffer.Count > p.group.maxBlocks) { return; } int index = p.level.PosToInt(x, y, z); if (depth > 2000) { origins.Add(index); return; } bits.Set(x, y, z, true); buffer.Add(index); if (fillType != DrawMode.verticalX) // x { if (CheckTile(p, (ushort)(x + 1), y, z, oldType, oldExtType)) { FloodFill(p, (ushort)(x + 1), y, z, oldType, oldExtType, fillType, bits, buffer, origins, depth + 1); } if (CheckTile(p, (ushort)(x - 1), y, z, oldType, oldExtType)) { FloodFill(p, (ushort)(x - 1), y, z, oldType, oldExtType, fillType, bits, buffer, origins, depth + 1); } } if (fillType != DrawMode.verticalZ) // z { if (CheckTile(p, x, y, (ushort)(z + 1), oldType, oldExtType)) { FloodFill(p, x, y, (ushort)(z + 1), oldType, oldExtType, fillType, bits, buffer, origins, depth + 1); } if (CheckTile(p, x, y, (ushort)(z - 1), oldType, oldExtType)) { FloodFill(p, x, y, (ushort)(z - 1), oldType, oldExtType, fillType, bits, buffer, origins, depth + 1); } } if (!(fillType == DrawMode.down || fillType == DrawMode.layer)) // y up { if (CheckTile(p, x, (ushort)(y + 1), z, oldType, oldExtType)) { FloodFill(p, x, (ushort)(y + 1), z, oldType, oldExtType, fillType, bits, buffer, origins, depth + 1); } } if (!(fillType == DrawMode.up || fillType == DrawMode.layer)) // y down { if (CheckTile(p, x, (ushort)(y - 1), z, oldType, oldExtType)) { FloodFill(p, x, (ushort)(y - 1), z, oldType, oldExtType, fillType, bits, buffer, origins, depth + 1); } } }
public void SingletonTest() { var singletonSet = new SparseBitSet(1); Assert.False(singletonSet.Get(0)); Assert.Equal(0, singletonSet.Cardinality); singletonSet.Set(0).Clear(0).Set(0); Assert.True(singletonSet.Get(0)); Assert.Equal(1, singletonSet.Cardinality); Assert.Equal(1, singletonSet.Length); Assert.Equal(0, singletonSet.NextSetBit(0)); Assert.Equal(-1, singletonSet.NextSetBit(1)); }
public void SingleChunkTest() { var singleChunkSet = new SparseBitSet(4096); Assert.Equal(0, singleChunkSet.Cardinality); singleChunkSet.Set(2345).Set(64); Assert.Equal(2, singleChunkSet.Cardinality); Assert.True(singleChunkSet.Get(64)); Assert.False(singleChunkSet.Get(65)); Assert.True(singleChunkSet.Get(2345)); Assert.False(singleChunkSet.Get(2346)); Assert.Equal(64, singleChunkSet.NextSetBit(0)); Assert.Equal(2345, singleChunkSet.NextSetBit(64 + 1)); Assert.Equal(-1, singleChunkSet.NextSetBit(2345 + 1)); }
public void NextSetBitTest() { var set = new SparseBitSet(10000); // 3 chunks, bits 0..9999 set.Set(0).Set(1).Set(2).Set(10).Set(100); // all in 1st chunk set.Set(5000).Set(5001).Set(5100); // all in 2nd chunk Assert.Equal(8, set.Cardinality); Assert.Equal(0, set.NextSetBit(0)); Assert.Equal(1, set.NextSetBit(1)); Assert.Equal(2, set.NextSetBit(2)); Assert.Equal(10, set.NextSetBit(3)); Assert.Equal(10, set.NextSetBit(10)); Assert.Equal(100, set.NextSetBit(11)); Assert.Equal(100, set.NextSetBit(100)); Assert.Equal(5000, set.NextSetBit(101)); Assert.Equal(5000, set.NextSetBit(5000)); Assert.Equal(5001, set.NextSetBit(5001)); Assert.Equal(5100, set.NextSetBit(5002)); Assert.Equal(5100, set.NextSetBit(5100)); Assert.Equal(-1, set.NextSetBit(5101)); // no next set bit }
public void PerformanceTest(int length, double maxAllowedSecs) { const int seed = 1234; var startTime = DateTime.Now; int count = length / 100; var largeSet = new SparseBitSet(length); var random = new Random(seed); for (int k = 0; k < count; k++) { int i = random.Next(length); largeSet.Set(i); } random = new Random(seed); for (int k = 0; k < count; k++) { int i = random.Next(length); Assert.True(largeSet.Get(i)); } random = new Random(seed); for (int k = 0; k < count; k++) { int i = random.Next(length); largeSet.Clear(i); } var elapsed = DateTime.Now - startTime; _output.WriteLine(@"size={0:N0} count={1:N0} set/get/clear elapsed={2}", length, count, elapsed); Assert.Equal(0, largeSet.Cardinality); Assert.True(elapsed < TimeSpan.FromSeconds(maxAllowedSecs), "Too slow"); }
public unsafe static List <int> FloodFill(Player p, int index, ExtBlock block, DrawMode mode) { Level lvl = p.level; SparseBitSet bits = new SparseBitSet(lvl.Width, lvl.Height, lvl.Length); List <int> buffer = new List <int>(); Queue <int> temp = new Queue <int>(); const int max = 65536; int count = 0, oneY = lvl.Width * lvl.Length; int * pos = stackalloc int[max]; pos[0] = index; count++; while (count > 0 && buffer.Count <= p.group.DrawLimit) { index = pos[count - 1]; count--; ushort x = (ushort)(index % lvl.Width); ushort y = (ushort)((index / lvl.Width) / lvl.Length); ushort z = (ushort)((index / lvl.Width) % lvl.Length); if (temp.Count > 0) { pos[count] = temp.Dequeue(); count++; } if (bits.Get(x, y, z)) { continue; } bits.Set(x, y, z, true); buffer.Add(index); if (mode != DrawMode.verticalX) // x { if (lvl.GetBlock((ushort)(x + 1), y, z) == block) { if (count == max) { temp.Enqueue(index + 1); } else { pos[count] = index + 1; count++; } } if (lvl.GetBlock((ushort)(x - 1), y, z) == block) { if (count == max) { temp.Enqueue(index - 1); } else { pos[count] = index - 1; count++; } } } if (mode != DrawMode.verticalZ) // z { if (lvl.GetBlock(x, y, (ushort)(z + 1)) == block) { if (count == max) { temp.Enqueue(index + lvl.Width); } else { pos[count] = index + lvl.Width; count++; } } if (lvl.GetBlock(x, y, (ushort)(z - 1)) == block) { if (count == max) { temp.Enqueue(index - lvl.Width); } else { pos[count] = index - lvl.Width; count++; } } } if (!(mode == DrawMode.down || mode == DrawMode.layer)) // y up { if (lvl.GetBlock(x, (ushort)(y + 1), z) == block) { if (count == max) { temp.Enqueue(index + oneY); } else { pos[count] = index + oneY; count++; } } } if (!(mode == DrawMode.up || mode == DrawMode.layer)) // y down { if (lvl.GetBlock(x, (ushort)(y - 1), z) == block) { if (count == max) { temp.Enqueue(index - oneY); } else { pos[count] = index - oneY; count++; } } } } bits.Clear(); return(buffer); }
protected override void Blockchange1(Player p, ushort x, ushort y, ushort z, byte type, byte extType) { p.ClearBlockchange(); CatchPos cpos = (CatchPos)p.blockchangeObject; byte oldType = p.level.GetTile(x, y, z), oldExtType = 0; if (oldType == Block.custom_block) { oldExtType = p.level.GetExtTile(x, y, z); } p.RevertBlock(x, y, z); GetRealBlock(type, extType, p, ref cpos); if (cpos.type == oldType) { if (cpos.type != Block.custom_block) { Player.SendMessage(p, "Cannot fill with the same type."); return; } if (cpos.extType == oldExtType) { Player.SendMessage(p, "Cannot fill with the same type."); return; } } if (!Block.canPlace(p, oldType) && !Block.BuildIn(oldType)) { Player.SendMessage(p, "Cannot fill with that."); return; } SparseBitSet bits = new SparseBitSet(p.level.Width, p.level.Height, p.level.Length); List <int> buffer = new List <int>(), origins = new List <int>(); FloodFill(p, x, y, z, oldType, oldExtType, cpos.mode, bits, buffer, origins, 0); int totalFill = origins.Count; for (int i = 0; i < totalFill; i++) { int pos = origins[i]; p.level.IntToPos(pos, out x, out y, out z); FloodFill(p, x, y, z, oldType, oldExtType, cpos.mode, bits, buffer, origins, 0); totalFill = origins.Count; } FillDrawOp op = new FillDrawOp(); op.Positions = buffer; int brushOffset = cpos.mode == DrawMode.normal ? 0 : 1; Brush brush = GetBrush(p, cpos, brushOffset); if (brush == null) { return; } if (!DrawOp.DoDrawOp(op, brush, p, cpos.x, cpos.y, cpos.z, cpos.x, cpos.y, cpos.z)) { return; } bits.Clear(); op.Positions = null; if (p.staticCommands) { p.Blockchange += new Player.BlockchangeEventHandler(Blockchange1); } }