Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this fabs implementation valid for NaNs?

I have the following, relatively straightforward (though not very efficient), implementation of the fabs function:

double fabs(double x) {
  if (x == 0.0) return 0.0; // deals with both 0.0 and -0.0.
  if (x > 0.0) return x; // deals with ]0.0 .. +inf], but "(NaN > 0.0)" is false
  return -x; // deals with [-inf .. 0.0[, and NaNs
}

The only "gotcha" I found with this implementation is the fact that, given a positive NaN, it returns a negative one. However, I could not find in the standard anything saying that this is not allowed.

In particular, here's what I found:

§7.12.7 :

Description

The fabs functions compute the absolute value of a floating-point number x.

Returns

The fabs functions return |x|.

This does not impose any constraints of things that are not numbers, i.e. NaNs.

F.10.4.2 :

The fabs functions

— fabs(±0) returns +0.

— fabs(±∞) returns +∞.

The returned value is exact and is independent of the current rounding direction mode.

Again, no constraints on NaNs.

F.10, item 11:

Functions with a NaN argument return a NaN result and raise no floating-point exception, except where stated otherwise.

No constraints on signedness.

In particular, I see no mention to the fact that signbit(fabs(x)) should return 0 for any floating-point x, which is essentially what my implementation violates.

However, Ignorantia juris non excusat, therefore I'd like to be certain that this implementation is conforming. It does not help that the libc implementations I found (glibc, musl) use all sorts of low-level bit tricks or compiler built-ins to be efficient, and therefore do not provide much information in this case.

Just to clarify, I added the language-lawyer tag because I'm more interested in what the standard itself requires than in what the compilers themselves do, although if they do things in "unexpected" manners (e.g. MSVC seems to keep the minus sign for -nan as reported by @WeatherVane), this could confirm that the standard is not so strict (but then again, MSVC is not a good example of standards-conformance anyway...).

like image 693
anol Avatar asked Jan 31 '26 14:01

anol


1 Answers

The C standard is lax about specifying floating-point behavior, except for annex F (which is optional), and a C implementation that conforms to the C standard without adopting annex F may behave as you indicate.

However, quality implementations will at least try to conform to IEEE 754-2008 (which is identical to the IEC 60559 mentioned in annex F of the C standard). IEEE 754-2008 says, in clause 5.5.1, that negating a floating-point operand (including a NaN) changes its sign bit.

like image 120
Eric Postpischil Avatar answered Feb 02 '26 05:02

Eric Postpischil



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!