Multidimentional fixed sized buffer #2513
Replies: 15 comments
-
How would this work internally? |
Beta Was this translation helpful? Give feedback.
-
@YairHalberstadt Internally it could be just as I said above, it actually just the same Surely it need more work. It need to cache the length of each dimension somewhere And about a slice, well this is challenging but still possible. We just need to tell the sub span about the dimension of original span. So that it will shift the row by the size of original span instead of it's row Suppose var span = float[4,4];
var subspan = span.Slice(1,1,2,2); // position 1,1 with size 2,2 but it should still know the original row size 4,4 too
subspan[0,0] // 1,1 of original span => (4 * (1 + 0)) + (1 + 0) == 5 of float buffer
subspan[1,0] // 2,1 of original span => (4 * (1 + 1)) + (1 + 0) == 9 of float buffer
subspan[0,1] // 1,2 of original span => (4 * (1 + 0)) + (1 + 1) == 6 of float buffer |
Beta Was this translation helpful? Give feedback.
-
@Thaina A pointer to the first item in the underlying array. And getting the element at [x, y] requires using all 7 of these bits of information. This makes the span 32 bytes, which is very large for a struct. At this point I don't see that you're gaining anything by using a ref struct, and would just define a type Array2Segment which requires no language changes. public class Array2Segment<T>
{
T[,] array;
int offsetX;
int offsetY;
int width;
int height;
this [int x, int y] => array[x + offsetX, y + offsetY];
} |
Beta Was this translation helpful? Give feedback.
-
@YairHalberstadt The benefit is all would be allocated on stack and don't need to garbage collected. Even it got a bit large it would have no memory footprint And also I just thought that, maybe we also don't need X and Y offset of the span. The pointer to first element is map to the same offset for each row if we just add by the width of the original span. So we just need
|
Beta Was this translation helpful? Give feedback.
-
I don't see how that would work. Can you share the code please? |
Beta Was this translation helpful? Give feedback.
-
@YairHalberstadt Suppose we have Matrix4x4 at memory 0 If we slice from 1,1 with size 2,2. It just virtually mapped the pointer 6,7,10,11 right? Without keeping the offset of X,Y I think if we know the width of original span, the pointer is the offset by itself. And we only go forward in slice so we don't really need to know how far back the original pointer is |
Beta Was this translation helpful? Give feedback.
-
@YairHalberstadt Actually we don't need a length of original array too. Because when we already sliced the new span we will just need to concern only the size of the slice itself So it just need
I think this is minimum. And a more complex dimension these numbers would growing by 2 per each dimension 3 dimensions might need
|
Beta Was this translation helpful? Give feedback.
-
@Thaina |
Beta Was this translation helpful? Give feedback.
-
Scrap that. You would have to know the width of the original array, not the length. |
Beta Was this translation helpful? Give feedback.
-
@YairHalberstadt Yes we need to know the memory layout But we don't need to know the full layout You don't need to know the height because the height of the new sliced span is the new height limit. And it must be ensure that both height and width plus offset will not larger than the original span since the |
Beta Was this translation helpful? Give feedback.
-
a multidimensional |
Beta Was this translation helpful? Give feedback.
-
How's about handling it C style? public struct Fixed4x4
{
private fixed float _data[4 * 4];
public ref float this[int x,int y] => _d[x*4 + y];
} An example usage might be:: var f = new Fixed4x4{
[0, 0] = 0, [0, 1] = 1, [0, 2] = 2, [0, 3] = 3,
[1, 0] = 4, [1, 1] = 5, [1, 2] = 6, [1, 3] = 7,
[2, 0] = 8, [2, 1] = 9, [2, 2] = 10, [2, 3] = 11,
[3, 0] = 12, [3, 1] = 13, [3, 2] = 14, [3, 3] = 15
};
Console.WriteLine(f[0,2]); // prints 2. And if you want to you can convert this into a span. |
Beta Was this translation helpful? Give feedback.
-
@mburbea I forgot to mention that I propose this feature to work inline in the function too. Not just field void DoSomething(int w,int h)
{
var M = stackalloc float[w,h];
M[1,1] = 1;
M[2,2] = 1;
} |
Beta Was this translation helpful? Give feedback.
-
No you've brought stackalloc in, that's something else. Multindexing doesn't make sense for pointers really |
Beta Was this translation helpful? Give feedback.
-
@Thaina , you can still use C style access with an extension method. static class Ext
{
public static ref T Get<T>(this ref Span<T> span, int x, int y, int yDim) where T: struct
{
return ref span[(x * yDim) + y];
}
}
...
static void DoSomething(int w,int h)
{
Span<float> r = stackalloc float[w * h];
r.Get(0, 1, h) = 1;
r.Get(0, 2, h) = 2;
} Pretty nice if you forget the math. If extension everything ever happens you might be able to even add an indexer (although you do somehow need to persist the idea of the yDim). You could also just create a struct like my previous suggestion and just cast the span to the struct. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
This should be possible
If possible I would like C# to also support multidimensional
Span2<T>
up toSpan4<T>
orSpan8<T>
and so the above struct could be changed toBeta Was this translation helpful? Give feedback.
All reactions