Document where matrix row writes are silently lost
The operator kept the [UnscopedRef] ref this[int] row indexer as is. design.md and the float2x2/float3x3 indexers now say where m[r][c] = v lands: locals, array elements, class fields, and ref locals keep the write; a readonly field, in parameter, property (auto-properties too), or static readonly identity takes a defensive copy, so the write compiles and is lost. Fix: copy to a local, write, assign back. Verified by compiling and running each case with Roslyn against CultMath (no diagnostics; writes land 5, lost 0). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
77ee6fe488
commit
6bc6db68d4
5 changed files with 7 additions and 0 deletions
|
|
@ -37,6 +37,11 @@ That makes these HLSL rules, not options:
|
|||
products go through `mul` (`mul(m, v)` treats `v` as a column, `mul(v, m)` as a
|
||||
row). `*` on matrices would be component-wise in HLSL, so CultMath does not
|
||||
define it.
|
||||
- `m[r][c] = v` writes through locals, array elements, fields of classes, and
|
||||
ref locals. Through a readonly field, an `in` parameter, a property
|
||||
(auto-properties included), or a static readonly value such as
|
||||
`float3x3.identity`, C# takes a defensive copy: the write compiles and is
|
||||
silently lost. Copy the matrix to a local, write to it, and assign it back.
|
||||
- Scalar/vector arithmetic and comparisons have explicit overloads on both
|
||||
sides rather than leaning on implicit scalar splat.
|
||||
- Intrinsics return HLSL's types and edge cases: `sign` returns `int`/`intN`
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ public struct float2x2 : IEquatable<float2x2>
|
|||
public float _m10 { readonly get => _row1.x; set => _row1.x = value; }
|
||||
public float _m11 { readonly get => _row1.y; set => _row1.y = value; }
|
||||
|
||||
/// <remarks>Writes through a readonly field, <c>in</c> parameter, property, or <c>identity</c> hit a defensive copy and are lost; write to a local and assign it back.</remarks>
|
||||
[UnscopedRef]
|
||||
public ref float2 this[int row]
|
||||
{
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ public struct float3x3 : IEquatable<float3x3>
|
|||
public float _m21 { readonly get => _row2.y; set => _row2.y = value; }
|
||||
public float _m22 { readonly get => _row2.z; set => _row2.z = value; }
|
||||
|
||||
/// <remarks>Writes through a readonly field, <c>in</c> parameter, property, or <c>identity</c> hit a defensive copy and are lost; write to a local and assign it back.</remarks>
|
||||
[UnscopedRef]
|
||||
public ref float3 this[int row]
|
||||
{
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue