Almost four years ago, I asked: how come q_rsqrt didn't force ufloat or udouble or whatever in her input. The Quake games never used this func for a negative input; this might raise a nasty native CPU error. Why not - I asked - force the positive input and crash gracefully?
Today I was watching some video on Youtube - I won't link it, it was AI - about the Year 2038 Bug. That's when the 31 bits, counting from the new year 1970, overflow. It's not 32 bits because it's a signed integer and they wanted to allow negative years, back to some time in 1901. I'm told December. Most people they cared about were born after then.
Another issue is that ye olde compilers from the earliest years of C, Ada, and Pascal were "type safe". If you had a big uint, they didn't like it when you made it an int. There was a chance you'd lop off the highest bit and make the whole thing meaningless. The compiler is your friend!
No really, he was written to be your friend. Programmers need to work with the compiler, not against him. Leave aside 2038. What could the Id Software doodz have done in the 1990s?
I'm thinking that before calling q_rsqrt, they could have sent their vectors into another function: which takes a float and squares it. "Pffft they probably did that already, x^2 or, better, x*x." Yeah, sure. And the base multiplication left the float as a float. We need a function that knows when x^[even uint] happens it sends back an unsigned value.
The problem is with the type of x. IEEE 754 didn't bother with "ufloat". There was no such thing in the 1990s. Why not? Because what "floats" is where the "point" is at, and sign is just one bit. They'd have to decide whether to add that bit to the top, or to the decimals. For the purpose of normalisation, which be taking the sum of three squares (so could be large), let's say we agreed to put it on the topside.
Now that we've decided to monkey with the structure of a hardwired type, which we can't do in software; we go to Intel HQ and we ring the doorbell with our proposal to alter their processor. It's 1994; maybe 1985 (Elite). Who's got space for that? And why does it matter so bad in, you know, a shmup game.
Blah blah blah, not worth the bother, never has been worth the bother. You know it, I (now) know it... everyone knows it (except apparently me). So why write alla'that. It's because here:
long i = * ( long * ) &y;
This type could be unsigned. (It also happens that "long" then meant 32-bit.) I just ran this by Google AI and...
uint32_t i; memcpy(&i, &y, sizeof(i)); i = 0x5f3759df - (i >> 1); memcpy(&y, &i, sizeof(y));
Chew on that, Kasper Nielsen!