Skip to content
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

Floating Point Min and Max #214

Closed
joncmu opened this issue Jun 23, 2015 · 10 comments
Closed

Floating Point Min and Max #214

joncmu opened this issue Jun 23, 2015 · 10 comments

Comments

@joncmu
Copy link

joncmu commented Jun 23, 2015

While reading through the design documents and some of the comments on issue #148 it seems like the definition for min and max does not follow the IEEE 754-2008 standard. The defined maxNum() and minNum() operations in the standard state that numeric values always win out against a qNaN value. Also the handling of sNaNs for maxNum and minNum is different than qNaN handling because any operation involving an sNaN shall deliver a qNaN as the result.
Therefore:
maxNum(numeric,sNan) = qNaN
maxNum(numeric,qNaN) = numeric

With the current definition where NaNs win out over numerics there is no difference between sNaN and qNaN handling.

One other question is are zeros ordered? The IEEE specification does not provide for any ordering but several other language specifications (Java, Go) have a similar definition to what is proposed except that zeros are ordered.

These are minute details that most people probably will never care about, but because of all of the differences it makes it difficult for CPU ISA designers to create efficient instructions for accelerating these operations.

@joncmu
Copy link
Author

joncmu commented Jun 23, 2015

Ignore my comment about zeros being ordered, I missed the statement that says for min and max they are. So WebAssembly is following the semantics of Java and Go.

@sunfishcode
Copy link
Member

We do have the IEEE 754-2008 maxNum and minNum operations as possible future features.

The current min and max functions follow several languages and map to single hardware instructions on ARM and others.

However, note that WebAssembly doesn't presently specify which particular NaN bit pattern you get back, and it doesn't presently distinguish between qNaN and sNaN. This is also something possible to be addressed in the future.

@joncmu
Copy link
Author

joncmu commented Jun 23, 2015

I missed the references to maxNum and minNum operations in the future features document. I know that the current min and max functions are supported on at least ARM and Altivec (for float32), as far as I know Intel does not support them as a single instruction.

@joncmu joncmu closed this as completed Jun 23, 2015
@titzer
Copy link

titzer commented Jun 23, 2015

We also haven't specified exactly what the min and max operations should
do. E.g. a straightforward desugaring could be

min(a, b) === a < b ? a : b

Which seems sane but gives weird results, such as -0.0 == min(0, -0), but 0
== min(-0, 0).

Unfortunately the latter seems to be what the Intel "minsd" instruction
does.

On Tue, Jun 23, 2015 at 5:41 PM, joncmu [email protected] wrote:

I missed the references to maxNum and minNum operations in the future
features document. I know that the current min and max functions are
supported on at least ARM and Altivec (for float32), as far as I know Intel
does not support them as a single instruction.


Reply to this email directly or view it on GitHub
#214 (comment).

@MikeHolman
Copy link
Member

FWIW, current design says:

min and max operations treat -0.0 as being effectively less than 0.0 .

@sunfishcode
Copy link
Member

@titzer The design already does give the NaN behavior and handling of zeros, so it already does rule out a<b?a:b.

@joncmu
Copy link
Author

joncmu commented Jun 23, 2015

Doing something simple like min(a,b) === a < b ? a:b would make mapping to hardware probably the simplest on the most architectures. All ISAs support floating point comparison and if condition flags are set a conditional move could be used to avoid branching, or a vector version and a select or blend instruction could then be use to select the two values. (Or if you are on Intel use minsd). Most of the floating point C code I have seen uses a macro with this behavior instead of using fmax/fmin. I would imagine that for 99% of the code that is written the coder doesn't care about the difference in NaN handling or ordered zeros.

@sunfishcode
Copy link
Member

A noted above, ARM and Altivec can do WebAssembly's min and max in a single instruction. Forcing them to do a<b?a:b would be a pessimization on those platforms. And, it would give us the weird semantics noted above. And weirdness of semantics is something we do take into consideration when making choices.

@titzer
Copy link

titzer commented Jun 24, 2015

On Wed, Jun 24, 2015 at 9:25 AM, Dan Gohman [email protected]
wrote:

A noted above, ARM and Altivec can do WebAssembly's min and max in a
single instruction. Forcing them to do a<b?a:b would be a pessimization on
those platforms. And, it would give us the weird semantics noted above. And
weirdness of semantics is something we do take into consideration when
making choices.

No, I agree that we would like the nicer min/max semantics, similar to
JavaScript Math.min/Math.max. I just brought this up because TurboFan
specifically optimizes a < b ? a : b to the Intel instruction and wondered
what semantics we had intended here.


Reply to this email directly or view it on GitHub
#214 (comment).

@sunfishcode
Copy link
Member

A quick update to this (old) issue: The latest IEEE 754-2018 draft introduces new minimum and maximum functions, including functions which essentially match the semantics of WebAssembly's (and various other languages') min and max. So, it appears WebAssembly is on a good path with respect to this topic.

Snektron added a commit to Snektron/zig that referenced this issue Oct 14, 2023
WebAssembly doesn't implement the correct semantics
for this operation. See WebAssembly/design#214
Snektron added a commit to Snektron/zig that referenced this issue Oct 14, 2023
The min and max builtins in Zig have some intricate behavior
related to floats, that is not replicated with the min and max
wasm instructions or using simple select operations. By lowering
these instructions to compiler_rt, handling around NaNs is done
correctly.

See also WebAssembly/design#214
Snektron added a commit to Snektron/zig that referenced this issue Oct 14, 2023
The min and max builtins in Zig have some intricate behavior
related to floats, that is not replicated with the min and max
wasm instructions or using simple select operations. By lowering
these instructions to compiler_rt, handling around NaNs is done
correctly.

See also WebAssembly/design#214
Snektron added a commit to Snektron/zig that referenced this issue Oct 15, 2023
The min and max builtins in Zig have some intricate behavior
related to floats, that is not replicated with the min and max
wasm instructions or using simple select operations. By lowering
these instructions to compiler_rt, handling around NaNs is done
correctly.

See also WebAssembly/design#214
Snektron added a commit to Snektron/zig that referenced this issue Oct 15, 2023
The min and max builtins in Zig have some intricate behavior
related to floats, that is not replicated with the min and max
wasm instructions or using simple select operations. By lowering
these instructions to compiler_rt, handling around NaNs is done
correctly.

See also WebAssembly/design#214
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants