Page 1 of 1

How to do Log2 ?

Posted: Tue May 29, 2012 10:47 pm
by TeraByte
I need the function Log2 and came up with the following:

Code: Select all

Define x.d, num.d
x = 8
num = Log(x)/Log(2)
which gives num = 2.99999999999996 which is close but not exact. The exact answer is 3 which is 2^3 = 8 or Log2(8) = 3. Perhaps this difference is due to floating point error.

QUESTION:
Is there a better way to calculate Log2 than the above?

Thank you.

Re: How to do Log2 ?

Posted: Tue May 29, 2012 11:06 pm
by skywalk
You already have the correct answer for a double.

Code: Select all

Define x.d, num.d
x = 8
num = Log(x)/Log(2)
Debug num
x = 3 * 6.1 / 2 / 6.1 * 2
Debug x
x = 3
Debug x

Re: How to do Log2 ?

Posted: Tue May 29, 2012 11:08 pm
by Shield

Code: Select all

#Log2 = 0.6931471805599453094

Define x.d
Define num.d

x = 8
num = Log(x) / #Log2

debug num

Re: How to do Log2 ?

Posted: Tue May 29, 2012 11:14 pm
by STARGĂ…TE
if you want to use it for quads and use only integers:

Code: Select all

Procedure Log2(Quad.q)
	While Quad <> 0
		Result + 1
		Quad>>1
	Wend
	ProcedureReturn Result-1
EndProcedure

Debug Log2(8)
Debug Log2(1024)

Re: How to do Log2 ?

Posted: Wed May 30, 2012 5:10 am
by wilbert

Code: Select all

Procedure.d Log2(x.d)
  Protected l.d = x
  !fld1
  !fld qword [p.v_l]
  !fyl2x
  !fstp qword [p.v_l]
  ProcedureReturn l
EndProcedure

Re: How to do Log2 ?

Posted: Wed May 30, 2012 2:57 pm
by TeraByte
Thank you for your excellent replies.

Re: How to do Log2 ?

Posted: Wed May 30, 2012 3:52 pm
by Little John
2wilbert:
Very cool! 8)

What is the minimal required prozessor for running this code?

Regards, Little John

Re: How to do Log2 ?

Posted: Wed May 30, 2012 4:22 pm
by wilbert
Little John, an old 486 processor should be sufficient.

Re: How to do Log2 ?

Posted: Wed May 30, 2012 4:26 pm
by Little John
Great, thank you!

Re: How to do Log2 ?

Posted: Thu May 31, 2012 12:32 am
by jack
a little shorter :twisted:

Code: Select all

Procedure.d Log2(x.d)
  !fld1
  !fld qword [p.v_x]
  !fyl2x
  ProcedureReturn
EndProcedure
return value can be left in st(0) :)

Re: How to do Log2 ?

Posted: Thu May 31, 2012 6:34 am
by wilbert
jack wrote:a little shorter
I know it's shorter.
The main reason why I did it a bit different is that I wasn't sure your solution would work on x64 since that officially expects a floating point value to be returned in xmm0.
I figured if I would PureBasic let handle the way it returns the value that that might be a more stable option. But maybe I'm wrong 8)

Another option, if you only need the integer part of the result and the source is a double is to do it like this

Code: Select all

x.d = 64
Debug PeekW(@x + 6) >> 4 - 1023
If both source and result are integer, you can also use bsr

Code: Select all

Procedure.i Log2(x.i)
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    !mov eax, -1
    !bsr edx, [p.v_x]
    !cmovnz eax, edx
  CompilerElse
    !mov rax, -1
    !bsr rdx, [p.v_x]
    !cmovnz rax, rdx
  CompilerEndIf
  ProcedureReturn
EndProcedure