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?

+3


source to share


2 answers


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

+4


source


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:



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.

+2


source







All Articles