I have floats that I want to divide, some of them may be zeros. How can I make it such that division by zeroes, when they happen, just return zero instead of NaN on x86-64?
I tried setting the FZ and DAZ flags of the MXCSR, to no avail. Am I misunderstanding something? Is Flush to Zero + Denormals Are Zero not supposed to make divisions by zero give zero?
#include <stdio.h>
#include <xmmintrin.h>
int main()
{
#define CSR_FLUSH_TO_ZERO (1 << 15)
#define CSR_DENORMALS_ARE_ZERO (1 << 6)
unsigned int csr = _mm_getcsr();
csr |= CSR_FLUSH_TO_ZERO;
csr |= CSR_DENORMALS_ARE_ZERO;
_mm_setcsr(csr);
__m128 a = { 0 };
__m128 b = { 0 };
a = _mm_div_ps(a, b);
float f[4];
_mm_store_ps(f, a);
printf("%f\n", f[0]); // prints out 'nan'
}
There's no MXCSR setting that will do that, you'll need an extra couple instructions (
cmppsagainst the divisor, andandpsorandnpson the result) to mask off the elements where the divisor input was==0.0f.Division by zero produces +-infinity, or NaN if the dividend was also zero. There's no subnormal output to Flush To Zero.
Enabling DAZ would make
0 / subnornaltreat the subnormal as exactly0.0fand give you NaN instead of0.0fwith a zero dividend. For a non-zero normalized dividend, you'd still get overflow to +-Infinity with a subnormal divisor.FTZ (Flush To Zero) only does anything if the result would be subnormal. It disables gradual underflow; that's the only case where flushing happens, not other cases that would raise other FP exceptions. DAZ (Denormals Are Zero) only does anything for subnormal (aka denormal).