Reputation: 30136
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:
Exponent bits of type double
are 52,53,54,55,56,57,58,59,60,61,62
Bit-size of double
equals bit-size of unsigned long long
equals 64
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
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
Reputation: 18964
For C++:
No. C++ does not require IEEE floating point. It doesn't even require binary exponents.
Absolutely not. Unsigned long long may be more than 64 bits. Double need not be 64 bits.
That sort of type punning is unsafe.
Upvotes: 2
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