I'm looking for an implementation of a three dimensional circular buffer in C# .NET that allows me to extract slices of the buffer.
I tried the multidimensional array but it doesn't allow me to get a specific slice of the buffer.
I also tried to implement a version using jagged array, but i have find some problems in understanding how to initialzie the matrix, and also in slice extraction.
Thanks for the help.
[EDIT 1]
The buffer will be used to store data from reltime sensors, it will be fixed in width height and the depth (time which be the circular part) will be defined by the user.
The slices i need will be a fixed size matrix (width and heigh with the data of a given time).
[EDIT 2]
The only implementation that i could implement that works. With the jagged array i'm still stuck at the declaration (i find it chaotic)
public class CircularBufferMatrix<T>
{
private readonly T[,,] _buffer;
public CircularBufferMatrix(int width, int height, int depth)
{
Width = width;
Height = height;
Depth = depth;
_buffer = new T[width, height, depth];
}
public T this[int x, int y, int z]
{
set { _buffer[x, y, z%Depth] = value; }
get { return _buffer[x, y, z%Depth]; }
}
#region Getters
public int Width { get; }
public int Height { get; }
public int Depth { get; }
#endregion
}
I would split these in two classes. You want something like a CircularBuffer class, which handles the reading and writing. The other could be an implementation of the 2D array you want to store. The reason of splitting these, is because you want to Read/write frames separately.
For example:
Circular buffer implementation:
public class CircularBuffer<T>
{
private T[] _buffer;
private int IncRollover(int value)
{
value++;
if (value >= _buffer.Length)
value = 0;
return value;
}
public CircularBuffer(int count)
{
_buffer = new T[count];
}
public bool Write(T element)
{
// if the writeindex (after increasing) equals the readindex, the buffer is full
var newWriteIndex = IncRollover(WriteIndex);
if (newWriteIndex == ReadIndex)
return false;
_buffer[WriteIndex] = element;
WriteIndex = newWriteIndex;
return true;
}
public bool TryRead(out T element)
{
if (ReadIndex == WriteIndex)
{
element = default(T);
return false;
}
element = _buffer[ReadIndex];
ReadIndex = IncRollover(ReadIndex);
return true;
}
public IEnumerable<T> ReadAll()
{
T element;
while (TryRead(out element))
yield return element;
}
public int ReadIndex { get; private set; }
public int WriteIndex { get; private set; }
}
This will take care of reading and writing induvidual 'frames'/slices. You can expand this class if you like to read on Index.
note: The write will return false if the buffer is full
This could be an implementation of the 2d buffers stored within the Circular buffer:
public class MyWhateverBuffer<T>
{
private CircularBuffer<T[,]> _buffer;
public int Width { get; private set; }
public int Height { get; private set; }
public int Depth { get; private set; }
public MyWhateverBuffer(int width, int height, int depth)
{
Width = width;
Height = height;
Depth = depth;
_buffer = new CircularBuffer<T[,]>(depth);
}
public T[,] New()
{
return new T[Width, Height];
}
public bool Add(T[,] buffer)
{
return _buffer.Write(buffer);
}
public bool TryRead(out T[,] buffer)
{
return _buffer.TryRead(out buffer);
}
public IEnumerable<T[,]> ReadAll()
{
return _buffer.ReadAll();
}
}
This class can be used like:
MyWhateverBuffer<double> myBuffer = new MyWhateverBuffer<double>(100, 100, 100);
var oneSlice = myBuffer.New();
oneSlice[10, 10] = 3.5;
oneSlice[50, 10] = 23.5;
oneSlice[10, 20] = 43.5;
myBuffer.Add(oneSlice);
var anotherSlice = myBuffer.New();
anotherSlice[10, 10] = 13.5;
anotherSlice[50, 10] = 23.5;
anotherSlice[10, 20] = 43.5;
var result = myBuffer.Add(anotherSlice);
if(!result)
{
// the buffer was full..
}
// Read the results from the buffer.
foreach(var slice in myBuffer.ReadAll())
{
Trace.WriteLine(slice[10, 10]);
}
You should always check if the buffer could be added. You don't want to lose info.
Side note:
The most profit gains with a Circular buffer is declaring the elements ones. Like big arrays will be reused every time.
If I understand your requirements correctly, you want a circular buffer consisting of items that are two dimensional arrays of data and the data from one item is never repeated in other items. C# doesn't have a cicular buffer type but you can always create one yourself:-
public class CircularBuffer <T> // make it generic
{
public class Iterator
{
public void MoveForward ();
public void MoveBackward ();
public T Item { get { } };
CicrcularBuffer <T> m_container;
LinkedListNode <T> m_current_item;
}
public void Add (T item);
public Iterator GetIterator ();
LinkedList<T> m_data;
}
Then create a class to contain your data:-
public class SensorData
{
// contains the two dimension data
}
And use it like:-
var buffer = new CircularBuffer <SensorData> ();
var iterator = buffer.GetIterator ();
var item = iterator.Item;
iterator.MoveForward ();
Obviously, there's a lot to be filled in but it should get you started.
Related
The CRC32DelimitedBufferWriter below saves a pointer to each span or memory when it is requested by a caller. When the caller advances the writer, it uses that pointer to access the bytes written so that it can maintain a running CRC32 calculation of the data written.
Does this work as intended? I believe that the spans and memories locations are not shifted between calls to GetSpan, GetMemory, and Advance, so I believe it's safe and will always work as expected but I'm not sure.
Have I used the most efficient technique for saving the address of the span or memory, and creating a ReadOnlySpan<byte> for accessing the data when the writer is advanced?
public unsafe struct CRC32DelimitedBufferWriter : IBufferWriter<byte>
{
private readonly IBufferWriter<byte> innerWriter;
private readonly CRC32Builder crcBuilder;
private byte* pointer;
private int bytesWritten;
public CRC32DelimitedBufferWriter(IBufferWriter<byte> innerWriter)
{
this.innerWriter = innerWriter;
this.crcBuilder = CRC32Builder.CreateInitialized();
this.bytesWritten = 0;
this.pointer = (byte*)0;
}
public Span<byte> GetSpan(int sizeHint = 0)
{
var span = this.innerWriter.GetSpan(sizeHint);
this.pointer = (byte*)MemoryMarshal.GetReference(span);
return span;
}
public Memory<byte> GetMemory(int sizeHint = 0)
{
var memory = this.innerWriter.GetMemory(sizeHint);
this.pointer = (byte*)memory.Pin().Pointer;
return memory;
}
public void Advance(int count)
{
this.crcBuilder.Add(new ReadOnlySpan<byte>(this.pointer, count));
this.innerWriter.Advance(count);
this.bytesWritten += count;
}
public void WriteCRCDelimiter()
{
var span = this.innerWriter.GetSpan(9);
span[0] = 255;
span.Slice(1).WriteInt(this.bytesWritten);
span.Slice(5).WriteInt((int)this.crcBuilder.Value);
this.innerWriter.Advance(9);
this.crcBuilder.Initialize();
this.bytesWritten = 0;
}
}
public static class SpanExtensions
{
public static void WriteInt(this Span<byte> span, int value)
{
for (var i = 0; i < 4; i++)
{
span[i] = (byte)value;
value >>= 8;
}
}
}
I am Trying to make a Game Engine in C# and OpenGL using OpenGL.NET. I have abstracted the Basic OpenGL Objects like VAO, VBO, etc. I Have a BufferLayout Class which specifies the Data present in the Vertex Buffer. The method in the VertexArray class that adds a buffer is this:
public void AddBuffer(uint index, ref VertexBuffer buffer)
{
Bind();
buffer.Bind();
uint i = index;
foreach (BufferElement element in buffer.Layout.Elements)
{
Gl.VertexAttribPointer(
i++,
element.GetComponentCount(),
Globals.ShaderDataTypeToOpenGLBaseType(element.Type),
element.Normalized,
buffer.Layout.Stride,
element.Offset
);
}
m_Buffers.Add(buffer);
}
This method has 2 Overloads: One which takes an IntPtr as the Offset and another which takes in an object.
This is the overload which takes in an object. But for some reason, the element.Offset is not working as expected. As I am only using a positions attribute for this test, it works when I replace element.Offset with null.
Here is BufferLayout.cs
public enum ShaderDataType
{
None,
Float, Float2, Float3, Float4,
Mat3, Mat4,
Int, Int2, Int3, Int4,
}
public class BufferElement
{
internal string Name;
internal ShaderDataType Type;
internal int Size;
internal int Offset;
internal bool Normalized;
public BufferElement(ShaderDataType type, string name, bool normalized = false)
{
Name = name;
Type = type;
Size = Globals.ShaderDataTypeSize(type);
Offset = 0;
Normalized = normalized;
}
internal void SetOffset(int offset) => Offset = offset;
public int GetComponentCount()
{
switch (Type)
{
case ShaderDataType.Float: return 1;
case ShaderDataType.Float2: return 2;
case ShaderDataType.Float3: return 3;
case ShaderDataType.Float4: return 4;
case ShaderDataType.Mat3: return 3 * 3;
case ShaderDataType.Mat4: return 4 * 4;
case ShaderDataType.Int: return 1;
case ShaderDataType.Int2: return 2;
case ShaderDataType.Int3: return 3;
case ShaderDataType.Int4: return 4;
}
return 0;
}
}
internal sealed class BufferLayout
{
public List<BufferElement> Elements { get; private set; }
public int Stride { get; private set; }
public BufferLayout(BufferElement[] e)
{
Elements = new List<BufferElement>();
Elements.AddRange(e);
CalculateOffsetsAndStride();
}
private void CalculateOffsetsAndStride()
{
int offset = 0;
Stride = 0;
for (int i = 0; i < Elements.Count; i++)
{
Elements[0].SetOffset(offset);
offset += Elements[0].Size;
Stride += Elements[0].Size;
}
}
}
The overload which takes an object is meant for compatibility profile OpenGL contex and the object has to be an object containing the vertex array data.
If you want to set an offset, then you have to create an IntPtr. e.g:
var offset = new IntPtr(element.Offset);
Gl.VertexAttribPointer(
i++,
element.GetComponentCount(),
Globals.ShaderDataTypeToOpenGLBaseType(element.Type),
element.Normalized,
buffer.Layout.Stride,
offset
);
Note, the offset and the stride parameter have to be specified in bytes.
First I would like to say that I am aware of different topics on true Randomness with seeds and how new Random() is created depending on Environment.TickCount.
Despite all that I couldn't figure out what my problem is.
I'm trying to create a population of 100 graphs for use in Graph Coloring Genetic Algorithm.
Every single population consists of set number of edges and set number of nodes. Every node has an index number and a random initial color.
That initial color is what I want to random. The colors are ints between 1 and 10.
But every single population looks the same, same nodes got same colors.
I probably might have missed something simple but I just cannot figure it out.
Any help would be appreciated.
CreatePopulation.cs
class CreatePopulation
{
private static Solution CreateRandomSolution(Graph graph, int colorsCount)
{
Solution solution = new Solution(graph, colorsCount);
for (int node = 0; node < graph.Nodes.Count; node++)
{
solution.assignColor(node, Program.RandomNumber(1, 10));
}
return solution;
}
public static List<Solution> CreateRandomPopulation(Graph graph, int populationSize)
{
List<Solution> list = new List<Solution>();
for (int i = 0; i < populationSize; i++)
{
list.Add(CreateRandomSolution(graph, 10));
}
return list;
}
}
Solution.cs holding future implementation of fitness methods and other methods needed for algorithm
class Solution
{
private int colorsCount;
private List<Vertex> edges;
private List<Node> nodes;
private Solution(List<Vertex> edges, List<Node> nodes, int colorsCount)
{
this.colorsCount = colorsCount;
this.edges = edges;
this.nodes = nodes;
}
public Solution(Graph graph, int colorsCount)
{
edges = graph.Vertices;
this.colorsCount = colorsCount;
this.nodes = graph.Nodes;
}
public void assignColor(int index, int color)
{
nodes[index].color = color;
}
}
Program.cs with main function
class Program
{
public static readonly Random Random = new Random();
private static double MutationRate = 0.05;
private static double CrossoverRate = 0.7;
private static int Colors = 10;
private static int GenerationCount = 100;
private static int PopulationSize = 100;
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
lock (syncLock)
{
return Random.Next(min, max);
}
}
static void Main(string[] args)
{
var graph = new Graph(#"C:\Users\Pawel\Desktop\lab1\GraphColoring-branch\bin\Debug\geom20.col");
var initPopulation = CreatePopulation.CreateRandomPopulation(graph, PopulationSize);
Console.ReadLine();
}
}
Node.cs
namespace Graph
{
class Node
{
public int number { get; set; }
public int color { get; set; }
public Node(int number)
{
this.number = number;
}
public Node() { }
}
}
Update
Changed the way I create a new List in Solution.cs but would like to know if it can be done in a nicer way.
public Solution(Graph graph, int colorsCount)
{
this.edges = graph.Vertices;
this.colorsCount = colorsCount;
this.nodes = new List<Node>(graph.Nodes.Count);
for (int i = 0; i < graph.Nodes.Count; i++)
{
this.nodes.Add(new Node{color = graph.Nodes[i].color, number = graph.Nodes[i].number});
}
}
The problem is every single one of your Solution objects are working from the same instance of List<Vertex> and List<Node>. So Random is working correctly, the real problem is you are overwriting the values for the previous solutions when generate the next solution.
The only constructor I see you use is
Solution solution = new Solution(graph, colorsCount);
In there you do
public Solution(Graph graph, int colorsCount)
{
edges = graph.Vertices;
this.colorsCount = colorsCount;
this.nodes = graph.Nodes;
}
This is just copying the reference of graph.Vertices and graph.Nodes, if any Solution modifies one of the items in the collections all Solutions get modified.
To fix this you need to make a deep copy of those two lists. You did not show what a Vertex or Node was, however if they are classes just doing
public Solution(Graph graph, int colorsCount)
{
edges = graph.Vertices.ToList();
this.colorsCount = colorsCount;
this.nodes = graph.Nodes.ToList();
}
will not be enough because that will only create a shallow copy of the list, your call to nodes[index].color = color; will still modify the nodes in all of the other graphs because although the lists are now separate references the elements in the list are still shared across Solution objects. You need something similar to
class Solution
{
private int colorsCount;
private List<Vertex> edges;
private List<Node> nodes;
private Solution(List<Vertex> edges, List<Node> nodes, int colorsCount)
{
this.colorsCount = colorsCount;
this.edges = edges;
this.nodes = nodes.Select(old => old.Clone()).ToList();
}
public Solution(Graph graph, int colorsCount)
{
edges = graph.Vertices;
this.colorsCount = colorsCount;
this.nodes = graph.Nodes.Select(old => old.Clone()).ToList();
}
public void assignColor(int index, int color)
{
nodes[index].color = color;
}
}
class Node
{
public int number { get; set; }
public int color { get; set; }
public Node(int number)
{
this.number = number;
}
public Node() { }
public Node Clone()
{
var newNode = new Node();
newNode.number = this.number;
newNode.color = this.color;
return newNode;
}
}
class Knight
{
public static readonly double LegalDistance = Math.Sqrt(5);
public Stack<Field> Steps { get; set; }
private static readonly List<Field> board = Board.GameBoard;
private static List<Field> fields;
private static readonly Random random = new Random();
private static readonly object synLock = new object();
public Knight(Field initial)
{
Steps = new Stack<Field>();
Steps.Push(initial);
}
public void Move()
{
Field destination = Choose();
if (destination == null)
{
return;
}
Console.WriteLine("Moving from " + GetPosition().GetFieldName() + " to " + destination.GetFieldName());
Steps.Push(destination);
}
public Field Back()
{
Field from = Steps.Pop();
Console.WriteLine("Moving back from " + from.GetFieldName() + " to " + GetPosition().GetFieldName());
return from;
}
public Field Choose()
{
List<Field> legalMoves = Behaviour();
legalMoves.RemoveAll(field => Steps.Contains(field, new FieldValueComparer()));
if (legalMoves.Count == 0)
{
return null;
}
Field theChoosenOne;
int index;
lock (synLock)
{
index = random.Next(0, legalMoves.Count);
}
theChoosenOne = legalMoves.ElementAt(index);
return theChoosenOne;
}
private List<Field> Behaviour()
{
fields = new List<Field>();
fields.AddRange(board);
for (int i = fields.Count - 1; i >= 0; i--)
{
double actualDistance = fields[i].GetDistance(GetPosition());
if (!actualDistance.Equals(LegalDistance))
{
fields.Remove(fields[i]);
}
}
return fields;
}
public List<Field> GetSteps()
{
return Steps.ToList();
}
public Field GetPosition()
{
return Steps.Peek();
}
}
So this is how I'd do the stuff. The problem is, I am missing some key functionality, because on low given stepcount it backtracks to the start, on high stepcount, it causes StackOverFlow.
Here are some other functions to let you understand what I want to do:
Calculating distance:
public double GetDistance(Field other)
{
return Math.Sqrt(Math.Pow(other.X - X, 2) + Math.Pow(other.Y - Y, 2));
}
Finding the path:
class PathFinder
{
public static void FindPath(Knight knight)
{
if (knight.Steps.Count != 20)
{
knight.Move();
FindPath(knight);
knight.Back();
}
}
}
Your path search is essentially random walk. On large board, this may take a while anyway.
Now about StackOverflow: notice that you don't push anything on Move() when there are no places to go. So, on recursive call to FindPath() there still will be the same knight.Steps.Count, the same position, the same null return on Choose()... and so on, until you're out of stack space.
Obvious fix would be to add bool return value to Move() indicating if there was any move. Unless there is actual reason behind using random moves, more deterministic search algorithm is recommended.
I have a 2d array of a class. The size of array is very large (around 3000*3000) and accessing the array with ordinary row and column method is taking very much time. For this purpose, I want to use pointers to access the array.
Following is my array code:
Class definition:
Class BoxData
{
Size _bound;
bool _isFilled=false;
Color _color=Colors.White;
public Size Bounds
{
get
{
return _bound;
}
set
{
_bound=value;
}
}
public bool IsFilled
{
get
{
return _isFilled;
}
set
{
_isFilled=value;
}
}
public Color FillColor
{
get
{
return _color;
}
set
{
_color=value;
}
}
}
Class used as array in application:
BoxData[,] boxData=new BoxData[3000,3000];
I want to access boxData with pointers.
Thanks
Try a jagged array instead of a multi dimensional one, they are faster in Microsoft's CLR implementation
BoxData[][] boxData=new BoxData[3000][];
for (int i=0; i<3000; i++)
boxData[i] = new BoxData[3000];
Maybe you could use a struct instead of a class for BoxData ?
Struct is a value type: as you declare your array, everything will be populated already.
You will not longer use a loop to create new BoxData() instances.
var x = new BoxData[3000,3000]; // Populated array of BoxData
Because of struct vs class restrictions, you will have to remove initializers this way...
struct BoxData
{
Size _bound;
bool _isFilled; // = false;
Color _color; // = Color.White;
public Size Bounds
{
get
{
return _bound;
}
set
{
_bound = value;
}
}
public bool IsFilled
{
get
{
return _isFilled;
}
set
{
_isFilled = value;
}
}
public Color FillColor
{
get
{
return _color;
}
set
{
_color = value;
}
}
}
...and initialize your default values using a loop will be much more faster.
for (int j = 0; j < 3000; j++)
for (int i = 0; i < 3000; i++)
x[i, j].FillColor = Color.White;