DevMaster.net Forums
[[ Home | Forums | 3D Engines Database | Wiki | Articles/Tutorials | Game Dev Jobs | IRC Chat Network | Contact Us ]]

Go Back   DevMaster.net Forums > Site Discussions > Code & Snapshot Discussion
User Name
Password
Register FAQ Members List Search Today's Posts Mark Forums Read

Reply
 
Thread Tools Search this Thread Display Modes
Old 08-16-2008, 08:00 AM   #1
deks
New Member
 
Join Date: Aug 2008
Location: Montreal, Canada
Posts: 3
Default

We often need to compute the log2 value for a particular number: finding the required power of two size of a texture, computing how many bits we need to send over the network for a particular value range, etc.

Here's my implementation, taking advantage of the FPU internal representation: converting the number into floating-point effectively converts it to the sign-exponent-mantissa representation of a float: we only need to extract the exponent and we're done:

Code:
unsigned long kFloorLogTwo(unsigned long Value) { unsigned long Result = 0; if(Value) { const float FloatValue = Value; Result = ((((*(unsigned long *)&FloatValue) & 0x7f800000) >> 23) - 127); } return Result; } unsigned long kCeilLogTwo(unsigned long Value) { unsigned long Result = 0; if(Value) { const float FloatValue = Value; Result = ((((*(unsigned long*)&FloatValue) & 0x7f800000) >> 23) - 126); } return Result; }
JF
deks is offline   Reply With Quote
Old 08-16-2008, 02:41 PM   #2
Nick
Senior Member
 
Join Date: Aug 2004
Location: Ghent, Belgium
Posts: 1,056
Default Re: Log2 functions

While that's vastly faster than the standard log2 function, there's an even faster approach using a processor independent intrinsic in Visual C++:
Code:
#include <intrin.h> inline unsigned long log2(int x) { unsigned long y; _BitScanReverse(&y, x); return y; }
Nick is offline   Reply With Quote
Old 08-16-2008, 07:23 PM   #3
deks
New Member
 
Join Date: Aug 2008
Location: Montreal, Canada
Posts: 3
Default Re: Log2 functions

Quote:
Originally Posted by Nick
While that's vastly faster than the standard log2 function, there's an even faster approach using a processor independent intrinsic in Visual C++:

Ahh, I didn't think of using BSR, thanks for the tip!

JF
deks is offline   Reply With Quote
Old 08-17-2008, 09:22 AM   #4
Blaxill
Member
 
Join Date: Jun 2005
Posts: 62
Default Re: Log2 functions

You need to keep in mind Nicks version is undefined for 0.

Slightly slower, but more accurate version for floats (posted on flipcode many moons ago.)
Code:
inline float fast_log2 (float val) { int * const exp_ptr = reinterpret_cast <int *>(&val); int x = *exp_ptr; const int log_2 = ((x >> 23) & 255) - 128; x &= ~(255 << 23); x += 127 << 23; *exp_ptr = x; val = ((-1.0f/3) * val + 2) * val - 2.0f/3; //(1) return (val + log_2); }
Quote:
The line (1) computes 1+log2(m), m ranging from 1 to 2. The proposed formula is a 3rd degree polynomial keeping first derivate continuity. Higher degree could be used for more accuracy. For faster results, one can remove this line, if accuracy is not the matter (it gives some linear interpolation between powers of 2).
Blaxill is offline   Reply With Quote
Old 08-17-2008, 09:44 AM   #5
Nils Pipenbrinck
Senior Member
 
Nils Pipenbrinck's Avatar
 
Join Date: Sep 2005
Location: Hamburg / Germany
Posts: 597
Default Re: Log2 functions

Be aware that casting float* to int* and similar stuff will break the strict aliasing rule and you'll run into serious trouble if you want to compile your code with newer GCC-compilers.

One way around this is to use unions, another is to include char* as a type during the cast. This one makes a magical connection between the two addresses and tells the optimizer to not assume that floats and ints never share the same memory space.

Compiles start to become aggressive when it comes to aliasing.. I'm sure the next VS will be much more aggressive as well.
___________________________________________
My music: http://myspace.com/planetarchh <-- my music

My stuff: torus.untergrund.net <-- some diy electronic stuff and more.
Nils Pipenbrinck is offline   Reply With Quote
Old 08-17-2008, 10:46 AM   #6
Blaxill
Member
 
Join Date: Jun 2005
Posts: 62
Default Re: Log2 functions

Nils, just out of interest, would GCC react the same way for both c++ reinterpret_cast and a c-style cast, or would it not complain about reinterpret_cast (the same response as to union type-punning) ?
Blaxill is offline   Reply With Quote
Old 08-17-2008, 04:33 PM   #7
Nick
Senior Member
 
Join Date: Aug 2004
Location: Ghent, Belgium
Posts: 1,056
Default Re: Log2 functions

Quote:
Originally Posted by Blaxill
You need to keep in mind Nicks version is undefined for 0.
Yes, but log(0) is always undefined anyway.

The easiest way to always get a well-defined result is to logic OR the input with 1. But obviously the programmer should always carefully check the behavior on a per-case basis.
Nick is offline   Reply With Quote
Old 08-17-2008, 04:37 PM   #8
Nick
Senior Member
 
Join Date: Aug 2004
Location: Ghent, Belgium
Posts: 1,056
Default Re: Log2 functions

Quote:
Originally Posted by Nils Pipenbrinck
Be aware that casting float* to int* and similar stuff will break the strict aliasing rule and you'll run into serious trouble if you want to compile your code with newer GCC-compilers.
Interesting. How about casting like (float&)i ? No (explicit) use of pointers here so possibly no aliasing trouble (plus, references are always constant anyway). Or are references treated like pointers with syntactic sugar?
Nick is offline   Reply With Quote
Old 08-18-2008, 01:47 AM   #9
Jare
Valued Member
 
Join Date: Oct 2005
Posts: 247
Default Re: Log2 functions

Quote:
Originally Posted by Nick
Interesting. How about casting like (float&)i ? No (explicit) use of pointers here so possibly no aliasing trouble (plus, references are always constant anyway). Or are references treated like pointers with syntactic sugar?
References are a form of typed aliasing, so they (should) have the same problem. Unions, on the other hand, are a language-supported method for aliasing the same memory with different types.

While the strict aliasing rule rarely causes problems in practice, and thus many people ignore it, it DOES cause problems sometimes, and they can be extremely hard and time-consuming to find. Always try to write the code using unions from the start.
___________________________________________
http://www.iguanademos.com/Jare
Jare is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Forum Jump


All times are GMT -7. The time now is 06:21 AM.


Powered by vBulletin
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.