What is the fastest way to write an IEEE-754 compliant double / floating subdivision in C ++?
I want to write compatible with the IEEE-754 division in C ++, especially with respect to dividing by zero control: positive/0->Inf
, negative/0->-Inf
, everything else/0->NaN
.
While simple C ++ splitting on my machine results in this very behavior, the C ++ standard does not require these semantics. It's undefined instead, so I can't rely on it.
So what is the fastest way to implement this in C ++? Of course, I can make an explicit test like this:
double fdiv64(double numerator, double denominator)
{
using limits=std::numeric_limits<double>;
if (denominator==0.0) {
if (numerator>0.0) {
return limits::infinity();
} else if (numerator<0.0) {
return -limits::infinity();
} else {
return limits::quiet_NaN();
}
} else {
return numerator/denominator;
}
}
But this introduces additional branches and is completely redundant on my machine, since I get the correct behavior anyway. There doesn't seem to be a built-in compiler that does the IEEE-754 splitting. I could use inline assembly, but that is also very disproportionate.
So what is the fastest way to do this separation?
source to share
You cannot do this in a portable manner, I'm afraid unless you create your own IEEE754 floating point implementation in software for platforms that don't natively use it, and even then there will be minor differences since your type will not be inline (e.g. , &&
and ||
will not be shorted if you overload them); although custom literals can help.
For example, support infinity
is optional and is only present on the platform if std::numeric_limits<T>::has_infinity == true
for your type T
.
So trying to optimize your supposedly portable code isn't even on the table.
Literature:
http://en.cppreference.com/w/cpp/types/numeric_limits/infinity http://en.cppreference.com/w/cpp/language/user_literal
source to share
You may already have it without doing anything special. On multiple architectures, you can specify what the CPU should do in "special" situations (divide by zero, etc.). Take a look fesetenv
. Compilers usually have switches about how they should handle floating point math. For example, take a look at Visual Studio cl.exe for an option about this.
If you stay on x86 architecture (and use SSE or x87 with internal precision set to float / double, see links below for details), I think you can rely on IEEE754 behavior out of the box (so your program will run on any x86 machine, not just yours).
If you have a processor that cannot follow IEEE754, you may have to use the full software floating point implementation. Or maybe you can use HW and you only need to handle exceptional cases.
But usually today almost everyone (PCs, mobile devices) uses IEEE754:
- Is it safe to assume that floating point is represented using IEEE754 floating point in C?
- Are there any real world processors using IEEE 754?
- I think the x86 architecture is fully IEEE754 compliant (SSE compliant out of the box, x87 requires the internal 80-bit precision to be fully compliant).
- ARM VFP is compatible and the new NEON (on armv8) is also compatible.
In SW implementation, you need to extract the sign, exponent, mantissa from the floating point number and do the math yourself.
Note. You can get inf result even if the divisor is not zero, but a small (subnormal) number. This is because the max. the number for float is in the range of ~ 10 ^ 38, but the minimum but positive number is in the range of ~ 10 ^ -45.
source to share