New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add indexer to MatrixXxX es (preferably ref returning) #21705
Comments
Ok, did some small testing and it turns out that i forgot that sample above wont work because one cant return by ref [StructLayout(LayoutKind.Sequential)]
public struct testStruct
{
public int field1;
public int field2;
public int field3;
public ref int this[int i] => ref Span<int>.DangerousCreate(this, ref field1, 3)[i];
} I made extremely simple struct like above and populated it with random numbers:
And console show expected values: Console.WriteLine(test[0]); //print 7
Console.WriteLine(test[1]); //print 0 (not initialized so zeromemory!)
Console.WriteLine(test[2]); //print 67 BTW sample above will work if you remove |
Hi @BreyerW , thanks for the suggestion. I think it is a reasonable addition. Most other matrix implementations do provide an indexer for convenience. I looked at OpenTK, SharpDX, and UnityEngine's Matrix types. GLSL and HLSL also allow matrix values to be indexed in a similar way. I'm not sure that we can provide a by-ref indexer, though. I don't fully understand the safety implications around returning a reference to a structure's field. Obviously, it's not permitted by regular C#. @jkotas, could you shed some light on those concerns? For what it's worth, I don't think the indexer being by-value is necessarily that bad. You probably don't want to be dynamically indexing into a matrix in a critical path, anyways. So it being slightly slower than using the fields directly, as a trade-off for actually being safe, is okay IMO. |
You have valid concerns of course. However if there is no performance loss (there might be a problem since Anyway, |
Yes, that would be a problem -- you're boxing on every call to the indexer. You could equivalently (?) use this pattern to avoid that:
Again, I don't think this is a generally safe pattern to use for a public API. Without the "ref return" part, I think we could move forward with the proposal. @tannergooding Any thoughts on this one? |
This pattern has GC hole. It will cause your app to crash in the GC intermittently. Do not ever do this. |
@jkotas Thanks for the confirmation. |
This is described in detail in dotnet/roslyn#5233 - look for " |
Can i ask if this feature have chance to appear with Since there is consensus that indexer shouldnt be |
The Unsafe class should help the performance compared to the switch statement, not hurt it. |
Could you clarify what you mean? Are you referring to this proposal? If so, that is already planned to be added, hopefully in the next release past 2.0. I have a branch which implements it, but it needs coordination with JIT changes in order to preserve SIMD functionality.
Right, I think that's the (only?) way to go. I don't really think there's any trickery that we can do with unsafe code or the |
@mellinoe exactly that proposal. I wanted to know if u feel fairly capable of adding indexer before next release in net core env. As for |
Right, jump tables are significantly slower than a simple indexing that you get by using Unsafe. |
I think we could quickly write up some perf tests to determine which version is faster. We should have the flexibility to choose either, with a small caveat. Right now, System.Numerics.Vectors doesn't rely on System.Runtime.CompilerServices.Unsafe, and we'd need to do some build configuration changes to allow it. But we could consider adding that dependency if we found that it was significantly better. |
Marking this as blocked given it needs the language rules around ref returns for structs expanded. |
@tannergooding |
I would like to be able to query any value of matrix using indexer
Like:
This is mainly convenience, but become big one if one want to get matrix property "randomly" e.g. in
for
loop. In this case one must write pretty bigif
else
block orswitch
.ref
might be useful to be able to send matrixes to graphic libraries efficiently and conveniently.Next use case is migrating between vector libraries that support indexers (like
OpenTk
) Note:ref
returning indexer shouldnt be problem there because omittingref
when calling means automatic dereference so in theory one could just changeusing
and recomplie without problems (assuming no issues with world coordinates etc.)Since
ref
andout
alternative methods got postponed, i think patch with them is perfect to include ref indexers as well unless you want to backport them to ealier versions of c# than 7EDIT: If you decide to implement ref indexer without changing internal representation, i think it could be implemented using
Unsafe.Add
. Something along these lines:EDIT 2: With spans available, you could implement indexers for retrieving only row or only column (return 4-elements span which is constructed using
DangerousCreate(this, ref this.MdesiredRow0, 4)
, Column is more tricky and probably would be implemented as tuple or float[4] since column arent layed out in continguous blocks, unless you add 'jumping' every X elements support to spans. Or just return span over whole matrix and force users to deal with 'jumping')The text was updated successfully, but these errors were encountered: