barak manos
barak manos

Reputation: 30136

Shift-left a 'double' operand

The following function shifts-left a double operand:

double shl(double x,unsigned long long n)
{
    unsigned long long* p = (unsigned long long*)&x;
    *p += n << 52;
    return x;
}

Is this function guaranteed to work correctly on all platforms?

You may assume a valid combination of x and n (i.e., x*2^n does not overflow).


In other words, I am asking whether or not the language standard dictates the following:

  1. Exponent bits of type double are 52,53,54,55,56,57,58,59,60,61,62

  2. Bit-size of double equals bit-size of unsigned long long equals 64

  3. Strict-aliasing rule for double and unsigned long long is not broken

If the answers for C and for C++ are different, then I would like to know each one of them.

Upvotes: 3

Views: 3000

Answers (3)

Ben Voigt
Ben Voigt

Reputation: 283634

No, neither C nor C++ dictates the representation of floating-point types in the language standard, although the IEEE format is recommended and a macro (__STDC_IEC_559__) is supposed to be available to detect whether it is in use.

Your solution has multiple problems in addition to different representations. You already spotted the strict aliasing violation... the optimizer might turn your whole function into a no-op, since no double is modified between the beginning of the function and the return value, it can assume x isn't changed. You could additionally have an overflow problem -- you would need some form of saturating arithmetic that doesn't allow the result to carry into the sign bit.

However, you don't need to mess with any of that, since the standard library already contains the function you're trying to write.

It is named ldexp (and ldexpf for float).

Upvotes: 10

Alan Stokes
Alan Stokes

Reputation: 18964

For C++:

  1. No. C++ does not require IEEE floating point. It doesn't even require binary exponents.

  2. Absolutely not. Unsigned long long may be more than 64 bits. Double need not be 64 bits.

  3. That sort of type punning is unsafe.

Upvotes: 2

gnasher729
gnasher729

Reputation: 52538

This code definitely doesn't shift a double operand to the left. It does some kind of bit manipulation, probably in the hope that the exponent of a double number would be changed.

As it is, the code invokes undefined behaviour, because an lvalue is written using the type long long and then read using the type double. As a result, anything could happen. That's the most unportable code you could get.

Upvotes: 1

Related Questions