Fast integer log2?

Started by
19 comments, last by Charles B 19 years, 9 months ago
I'm looking for a really fast integer log2. It can assume that the input is always a power of 2, or it can simply round off non-pow2, or whatever. This is partly useful for me and mostly just curiosity to see what kind of wacky optimizations/fast routines you guys can come up with.
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
Advertisement
x86 ASM opcode: BSR (bit scan reverse). Returns the index of the highest non-zero bit. I.e. the log base two, rounding down.
Results are undefined if the original number is zero.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Damn, that was easy.

[EDIT] Uh...I'm not too good with assembly. If I tell it to put the result in eax, can I use that to not give the function a real return statement?
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
DWORD dwNumber=something other than 0;DWORD dwLog2;__asm{	mov	dwLog2, dwNumber	bsr	dwLog2}


I'm not good with asm (well not x86 at least) either, but that would be my best guess. Maybe someone can point out any mistakes I made?
Bungo!
int pow2( int x ){	__asm 	{		bsr eax, x		ret	}	//dummy return	return 0;}


That caused an access violation. I thought return values were in eax?
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
If you're using MSVC, look up declspec(naked) for the function type.
Here is the code with stack prolog-epilog code:

#include <iostream>using namespace std;// logarithm function__declspec (naked) int log2(int val){	// prepare stack	__asm {        push   ebp        mov      ebp, esp        sub      esp, __LOCAL_SIZE	}	__asm {		mov eax,[val]		jz log2end		bsr eax,eaxlog2end:	}	// Cleanup function    __asm      {        mov      esp, ebp        pop      ebp        ret    }}int main(){	cout << "Result: " << log2(2) <<endl;	return 0;}
The zero case will not work correctly for that however. mov doesn't set flags, you need a test as well
Quite right. Change to:

	__asm {		mov eax,[val]                test eax,0		jz log2end		bsr eax,eaxlog2end:	}
Cool.

Now can you explain to me how the prolog code works, and why you need test?
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.

This topic is closed to new replies.

Advertisement