I don’t understand how the following C conversion functions work (and why they’re written this way); I’m fairly certain that the original author knew what he was doing:
typedef union TValue {
uint64_t u64;
double n;
struct {
uint32_t lo; /* Lower 32 bits of number. */
uint32_t hi; /* Upper 32 bits of number. */
} u32;
[...]
} TValue;
static int32_t num2bit(double n)
{
TValue o;
o.n = n + 6755399441055744.0; /* 2^52 + 2^51 */
return (int32_t)o.u32.lo;
}
static uint64_t num2u64(double n)
{
#ifdef _MSC_VER
if (n >= 9223372036854775808.0) /* They think it's a feature. */
return (uint64_t)(int64_t)(n - 18446744073709551616.0);
else
#endif
return (uint64_t)n;
}
- Does num2bit actually just cast a
doubleintoint32_t? Why the addition? Why write it like this? - What is this “feature” that is alluded to in num2u64? (I believe _MSC_VER means it’s the code-path for Microsofts C compiler).
Note that those functions are not always used (depending on CPU architecture), this is for little-endian (I resolved some preprocessor macros to simplify).
Links to online browseable mirror (the code is from the LuaJIT project):
Surrounding Header file (or whole project).
Every hint is appreciated.
num2bit is designed to implement the Lua BitOp semantics especially wrt. modular arithmetic. The implementation-defined behavior is well under control, since LuaJIT only works for specific CPUs, platforms and compilers, anyway. Don’t use this code anywhere else.
num2u64 is a workaround for a bug/misfeature of MSVC where it always converts double to uint64_t via int64_t. This doesn’t give the desired results for numbers >= 2^63. MS considers this abomination a ‘feature’. Duh.