I've been taking a look at the x64 software developer manual and it looks like the built-in {MIN|MAX}{S|P}{S|D} instructions do not implement the functions that are called minNum and maxNum in the IEEE 754 standard, despite Intel claiming in the same document that their CPUs are fully compliant.
Intel operations always return the second operand if either operand is a QNaN and neither is an SNaN, while minNum and maxNum return the other operand, i.e.:
IEE 754:
minNum(1.0, QNaN) -> 1.0
minNum(QNaN, 1.0) -> 1.0
Intel x64:
MIN(1.0, QNaN) -> QNaN
MIN(QNaN, 1.0) -> 1.0
Am I correct that standard-compliant minNum/maxNum functions have to be emulated with an additional check of the first operand and cannot be directly translated to the corresponding instructions?
Yes, you are going to need extra instructions.
It is discussed in this comment on a Julia issue thread by Arch Robinson:
The semantics of minsd were designed back in the '90s, well before IEEE 754-2008, so that compilers could optimize the common C idiom
x<y?x:y
.
The issue goes on to suggest a sequence of AVX instructions for making it NaN-poisoning. If instead you want IEEE behaviour, then you could use
VMIN R, a, b // result is b if a or b are NaN, min(a,b) otherwise
// so Nan is not propagated only if a is the NaN
VCMPNEQ M, b, b // M=11…11 if b is NaN, 0 otherwise
VBLENDV Res, R, a, M // Res = R if M=0 (b not NaN), otherwise Res=a (if b is NaN)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With