Closed PavielKraskouski closed 1 year ago
Tagging subscribers to this area: @dotnet/area-system-numerics See info in area-owners.md if you want to be subscribed.
Author: | PavielKraskouski |
---|---|
Assignees: | - |
Labels: | `api-suggestion`, `area-System.Numerics` |
Milestone: | - |
Is this also relevant to Vector<T>
This isn't a standard operation exposed by other libraries with vector support. It likewise doesn't really "fit" from a mathematical perspective and wouldn't provide any benefits performance wise nor would it do anything like reduce allocations. This is really just saving the user from typing a few characters and at the cost of making the code harder to read/understand.
Noting this is different from multiplication where multiplying by a scalar is a well-defined operation. It is likewise different from multiplication by a matrix where the Vector can be viewed as a 4x1
or a 1x4
matrix and thus can be multiplied by or multiply a 4x4
matrix (depending on if the input is interpreted as row or column major, etc).
But then why does HLSL have the float3
type and GLSL have the vec3
type, which allow these operations?
I needed to adapt this HLSL code: https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
Let's take a look at this function:
float3 RRTAndODTFit(float3 v)
{
float3 a = v * (v + 0.0245786f) - 0.000090537f;
float3 b = v * (0.983729f * v + 0.4329510f) + 0.238081f;
return a / b;
}
The same in C# would look like this:
Vector3 RRTAndODTFit(Vector3 v)
{
Vector3 a = v * (v + new Vector3(0.0245786f)) - new Vector3(0.000090537f);
Vector3 b = v * (0.983729f * v + new Vector3(0.4329510f)) + new Vector3(0.238081f);
return a / b;
}
Or like this:
Vector3 RRTAndODTFit(Vector3 v)
{
Vector3 a = v * (v + 0.0245786f * Vector3.One) - 0.000090537f * Vector3.One;
Vector3 b = v * (0.983729f * v + 0.4329510f * Vector3.One) + 0.238081f * Vector3.One;
return a / b;
}
In my opinion, the HLSL code looks more elegant and simple, while the C# code looks bloated.
But then why does HLSL have the float3 type and GLSL have the vec3 type, which allow these operations?
Those are shader languages which are designed around GPU computation and which may be able to accelerate or optimize such operations. This is possible because GPUs are often SIMT rather than SIMD.
It is not typical for the corresponding CPU side libraries to provide such operations. Some examples of widely popular libraries that do not provide such operations includes Unity, Unreal, XNA, DirectX Math, and many other vector libraries. GLM is possibly the one notable exception, but it specifically attempts to be a CPU side mirror of GLSL and doesn't strictly take into account other design points or considerations.
In my opinion, the HLSL code looks more elegant and simple, while the C# code looks bloated.
It is ultimately a matter of opinion. To me, the C# code makes the actual steps necessary for computation explicit and clear. I've found this is important for perf critical code which is a typical use case for the vector types.
The type of CPU you'll typically find is SIMD and none of the current major hardware vendors provide any instructions for accelerating vector addition or subtraction by a scalar. Because of this, the real world impact is that v + scalar
would have to compile down to some form of "broadcast". In the case scalar
is a constant, this can be an 8/12/16-byte constant loaded from memory. In the case it isn't a constant, it will be an actual broadcast/duplicate/splat instruction.
This is unlike for multiplication
or division
where they are actual operations that are well-defined for euclidean vectors and where hardware often provides acceleration for them. Arm64 for example has both MultiplyByScalar
and MultiplyBySelectedScalar
instructions available for use.
Background and motivation
Multiplication and division operators involving floats and vectors are currently available. At the same time, only two vectors can be added and subtracted. For example, in my software renderer, there are situations where you need to add or subtract a float from a vector. I propose to add methods for adding and subtracting floats with vectors.
API Proposal
API Usage
Alternative Designs
No response
Risks
No response