Skip to content

The documentations of Vector*.Clamp/ConvertTo*Int*/Max/Min are unclear #11280

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

Open
tfenise opened this issue May 7, 2025 · 3 comments
Open
Labels
area-System.Runtime.Intrinsics untriaged New issue has not been triaged by the area owner

Comments

@tfenise
Copy link
Contributor

tfenise commented May 7, 2025

Type of issue

Missing information

Description

There are Vector*.ClampNative/ConvertTo*Int*Native/MaxNative/MinNative which are documented to use platform specific behavior in certain cases. However, it is not clear from the documentations what Vector*.Clamp/ConvertTo*Int*/Max/Min do in those cases.

Some of those methods like Vector128.Max are documented to match IEEE 754:2019, but the information is still missing for other methods including Vector512.Max.

Page URL

https://learn.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.vector512.min?view=net-10.0

Content source URL

https://github.com/dotnet/dotnet-api-docs/blob/main/xml/System.Runtime.Intrinsics/Vector512.xml

Document Version Independent Id

9570ebc0-e5e1-92cf-bf93-05bf4d0017bb

Platform Id

3c28a4a4-e457-e6d2-1cd9-32698ff859c0

Article author

@dotnet-bot

@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label May 7, 2025
@tannergooding
Copy link
Member

However, it is not clear from the documentations what Vector*.Clamp/ConvertToInt/Max/Min do in those cases.

It is not documented because it is hardware dependent. Given two CPUs it may have entirely different behaviors.

Vector128.MinNative for example is documented as:

Compare two vectors to determine which is lesser on a per-element basis using platform specific behavior for NaN and NegativeZero.

This covers that it picks the lesser of left vs right on a per-element basis, but the behavior of NaN and NegativeZero is platform specific. So for most values it does what you expect, but for NaN and NegativeZero it could do something different. We aren't going to document this, because we aren't going to make guarantees what a given piece of hardware will do (and often cannot guarantee this over time).

An example of this is that on Arm64 hardware it will just continue emitting fmin because this is a single instruction that already does the right thing and is the fastest single instruction. If a faster single instruction existed in the future, we might switch to that instead, provided it met the guarantees presented above (behaving correctly for all inputs that are not NaN or NegativeZero).

Alternatively, on most x64 hardware we will emit minps which will return right if either input is NaN or if both inputs are zero with opposite signs. However, on newer AVX512DQ capable hardware we have access to vrangeps which takes the same amount of time but allows you to ensure that -0 is returned if both inputs are zero with opposite signs. However, vrangeps does not allow you to have IEEE 754 compliant behavior for NaN. Rather, if one input is sNaN and the other a regular value, it will return qNaN; whileif one input is qNaN and the other a regular value, it will return the regular value. On AVX10.2 capable hardware we will get access to a new vminmaxps instruction which will let us have the IEEE 754 compliant behavior in a single instruction, assuming it is as fast as minps and vrangeps we will likely switch to it instead.

However, such behaviors aren't guaranteed. The entire purpose of the *Native functions is it is dependent on the native machine you're targeting, so we are free to change it over time provided the documented invariant is kept. It will be deterministic within a single run, but can otherwise differ in behavior for the listed edge cases.

Some of those methods like Vector128.Max are documented to match IEEE 754:2019, but the information is still missing for other methods including Vector512.Max.

This looks like it somehow got dropped from Vector64/Vector256/Vector512. It exists in the source.

@gewarren, is there an easy way to get these docs repopulated from the C# XML documentation comments to ensure remarks like this are consistent across the APIs? It looks like there might be quite a few cases like this where Vector128 has remarks or other documentation but Vector64/256/512 are missing them

@tfenise
Copy link
Contributor Author

tfenise commented May 10, 2025

The question is about the documentations of the non-native versions, not the native versions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Runtime.Intrinsics untriaged New issue has not been triaged by the area owner
Projects
None yet
Development

No branches or pull requests

3 participants