Earlier quoted context omitted.
That's the Linux way to do it union { int i; float f } u { .f = 1.23f }; int i = u.i; Another way is a memcpy, which I believe is the most defined way to do type punning int i; float f; memcpy(&i, &f, 4); But you also have to assume the size of those primitive types but that's pretty safe in modern C/C++.
In C++, type punning through pointers and unions is undefined behavior. Even `reinterpret_cast ` isn’t allowed because of aliasing (IIRC). The only “defined” way to do type punning is a memcpy. A compiler targeting something like x86 would optimize out the memcpy. For more information, see the C++20 final draft[0§7.6.1.9] [0]: https://isocpp.org/files/papers/N4860.pdf
Fast Inverse Square Root
81–90 of 100 posts
Re: Fast Inverse Square Root
#82It may be useful to mention that modern architectures often have vectorized instructions like vrsqrt14ps (accessible via the _mm512_rsqrt14_ps intrinsic) that provides a 14-bit approximation (there are more accurate variants too) in every lane with an inverse throughput of 2. These are faster than the integer bit hacks. https://software.intel.com/sites/landingpage/IntrinsicsGuide...
That way you can quickly get the precision that you want ;)
Re: Fast Inverse Square Root
#83To me "inverse square root" means "square" so it makes the title of this kind of funny.
Re: Fast Inverse Square Root
#84Earlier quoted context omitted.
In C++, type punning through pointers and unions is undefined behavior. Even `reinterpret_cast ` isn’t allowed because of aliasing (IIRC). The only “defined” way to do type punning is a memcpy. A compiler targeting something like x86 would optimize out the memcpy. For more information, see the C++20 final draft[0§7.6.1.9] [0]: https://isocpp.org/files/papers/N4860.pdf
I always thought the memcopy is optimized out, but can you explain how in int i; float f; memcopy (&i, &f,4) the memcopy can be optimized out? Probably I am misunderstanding the statement.
Re: Fast Inverse Square Root
#85What was the speedup from this? If only 1% of cpu time was spent on slow square root, and this sped it up by 100%, it would be barely worth it.
> If only 1% of cpu time was spent on slow square root, and this sped it up by 100%, it would be barely worth it. If you can do 10,000 things with 1% cpu time, and you are now able to do 5,000 more things, is it still not worth it?
Re: Fast Inverse Square Root
#86A little self-promotion: I've written a blog post to answer the question that this one ends with (how to optimize divisions by constant integers): https://rubenvannieuwpoort.nl/posts/division-by-constant-uns... https://ridiculousfish.com/blog/posts/labor-of-division-epis... and https://ridiculousfish.com/blog/posts/labor-of-division-epis... also explain this (and are probably better written than my blogpost).
Very nice page! Minor nit, there's a typo here in the power-of-two example: uint divide(uint n) { return n the shifts should be to the right, obviously.
Re: Fast Inverse Square Root
#87It may be useful to mention that modern architectures often have vectorized instructions like vrsqrt14ps (accessible via the _mm512_rsqrt14_ps intrinsic) that provides a 14-bit approximation (there are more accurate variants too) in every lane with an inverse throughput of 2. These are faster than the integer bit hacks. https://software.intel.com/sites/landingpage/IntrinsicsGuide...
So all the major platforms, CPUs and GPUs, implement the fast reciprocal square root to decent amounts of accuracy, without any need of bit-twiddling anymore.
Re: Fast Inverse Square Root
#88Earlier quoted context omitted.
I always thought the memcopy is optimized out, but can you explain how in int i; float f; memcopy (&i, &f,4) the memcopy can be optimized out? Probably I am misunderstanding the statement.
The compiler is not beholden to the standard library but the standard. So all modern compilers come with a bit of knowledge of how standard library functions like memcpy are supposed to behave and as long as the visible effect is the same it's allowed to do anything it wants. So instead of calling the function memcpy for a size of 4, it can e.g. just use a mov instruction to move the value from a float to an integer…
Re: Fast Inverse Square Root
#89 float InvSqrt(float x)
{
long yl;
float y;
yl = 0x5f3759df - ((*(long *) &x) >> 1);
y = *(float *) &yl;
return y * (1.5F - (x * 0.5F * y * y));
}Re: Fast Inverse Square Root
#90> Games calculate square roots and inverse square roots all the time to find the lengths of vectors A trick here is that one often doesn't have to do the square root. For instance, if you want something to happen when an object is 5 units away from another object, it's normal to do if sqrt( (x2-x1)^2 - (y2-y1)^2 ) but instead you can do if (x2-x1)^2 - (y2-y1)^2 trading a sqrt for a squaring. And often the square of t…
Sometimes you can even get away by dropping the square completely: if (x2-x1) - (y2-y1) I once used this in a path tracer to speed things up a little. The results where less accurate but sometimes this can be used as trade-off.