7

If I have 2 denormal floating point numbers with different bit patterns and compare them for equality, can the result be affected by the Denormals-Are-Zero flag, the Flush-to-Zero flag, or other flags on commonly used processors?

Or do these flags only affect computation and not equality checks?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Zachary Burns
  • 453
  • 2
  • 9
  • 2
    There is no `FTZ` or `DAZ` for x87, only for `SSE`. – EOF Jan 04 '19 at 23:47
  • `FTZ` has no effect, since it flushes to zero denormal floating-point results, and a comparison for equality does not produce a floating-point result but a Boolean one. `DAZ` has an effect, since it tells the processor to consider all denormals as the same thing, namely 0. – Iwillnotexist Idonotexist Jan 05 '19 at 00:32

1 Answers1

7

DAZ (Denormals Are Zero) affects reading input, so DAZ affects compares. All denormals are literally treated as -0.0 or +0.0, according to their sign.

FTZ (Flush To Zero) affects only writing output, so FTZ doesn't affect compares. Compares don't produce an FP output, so there's nothing to flush.


(DAZ and FTZ are flags in the SSE MXCSR control/status register. There is no equivalent for x87.)


Why do both flags exist separately, instead of one flag controlling both things? I don't know, but you definitely need both effects.

You might be reading FP data from a file, or from the network, so you could get denormal inputs directly, not the result of your calculations. So you need DAZ for that.

Producing a correct denormal output (e.g. from subtracting nearby normal numbers, or multiplying two small normal numbers) is potentially slow, so you need FTZ to allow the CPU to just underflow to +-0.0 instead of taking a microcode assist to get the right value.


Or you might have one thread run with fast-math (FTZ+DAZ), while another thread runs with precise math for some computations that require it. If the fast-math thread reads data produced by the precise thread, those numbers might be denormals.

I'm not sure what a use-case would be for setting DAZ but not FTZ, or vice versa. It would certainly involve reading data you didn't produce yourself, or writing data for readers other than yourself, otherwise just FTZ is sufficient to avoid any slowdowns.

(Just DAZ alone is not sufficient: producing a denormal output from normal inputs is still slow, even if the next operation treats it as 0.)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • FWIW, some short code I wrote to actually test that: https://pastebin.com/L3LTvbQJ – Iwillnotexist Idonotexist Jan 05 '19 at 00:36
  • @IwillnotexistIdonotexist: nice. I think I tested it myself when playing around with an asm implementation of [`nextafter`/`nextafterf`](https://en.cppreference.com/w/c/numeric/math/nextafter), which has to compare is inputs to see which direction to step. I even asked [Implementing std::nextafter: Should denormals-are-zero mode affect it? If so, how?](https://scicomp.stackexchange.com/q/23191), but never got back to it. – Peter Cordes Jan 05 '19 at 00:47
  • 1
    That is _such_ a thorny question. I can make good arguments for almost any interaction of `nextafterf()` with DAZ/FTZ. I am of two minds: **Either** `nextafterf()` trusts the user and unconditionally gives the next float, denormal or not, and the user must keep in mind that the other flags may make `f-nextafterf(f, ...) == 0`; **Or** `nextafterf()` doesn’t trust the user and returns the next normal number or 0. In this case it would honor DAZ and ignore FTZ. Honoring FTZ or both would lead to situations where `f != next(prev(f))`, which I find unacceptable. – Iwillnotexist Idonotexist Jan 05 '19 at 02:09