Rounding to the next power of two

Share your advanced PureBasic knowledge/code with the community.
User avatar
❤x1
User
User
Posts: 46
Joined: Thu Jan 10, 2019 5:56 pm

Rounding to the next power of two

Post by ❤x1 »

Code: Select all

Procedure RoundPow(Number)
	Number - 1
	Number = (Number | Number >> 1)
	Number = (Number | Number >> 2)
	Number = (Number | Number >> 4)
	Number = (Number | Number >> 8)
	Number = (Number | Number >> 16)
	
	CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
		Number = (Number | Number >> 32)
	CompilerEndIf
	
	ProcedureReturn Number + 1
EndProcedure

Debug RoundPow(67)
eck49
Enthusiast
Enthusiast
Posts: 153
Joined: Sat Nov 14, 2020 10:08 pm
Location: England

Re: Rounding to the next power of two

Post by eck49 »

Clever!

A very elegant application of binary arithmetic.
Ubuntu 22.04 64-bit
Purebasic 6.00 (as of 5 Sep 2022)
(native tongue: English)
BarryG
Addict
Addict
Posts: 3324
Joined: Thu Apr 18, 2019 8:17 am

Re: Rounding to the next power of two

Post by BarryG »

Since I'm a bit dumb, when would you need this type of trick? Can you give an example? I like to learn. Thanks.
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Rounding to the next power of two

Post by Keya »

I think you can also use the Intel assembly instruction "bsr" (bitscan reverse) for this
User avatar
skywalk
Addict
Addict
Posts: 3999
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Rounding to the next power of two

Post by skywalk »

This is faster than the direct way with pow() function. I will use it. :)
Useful when sampling discretely and FFT samples must be powers of 2.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
idle
Always Here
Always Here
Posts: 5095
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Rounding to the next power of two

Post by idle »

Yes a nice tip if you need to call it frequently the assembly equivalent would be like this.

Code: Select all

Procedure RoundPowUP(Number) 
  CompilerIf SizeOf(Integer) = 8
    !mov rdx,[p.v_Number] 
    !sub rdx, 1
    !bsr qword rcx , rdx
    !add rcx,1
    !shl rax,cl 
  CompilerElse
    !mov edx,[p.v_Number] 
    !sub edx, 1
    !bsr qword ecx , edx
    !add ecx,1
    !shl eax,cl 
  CompilerEndIf   
  ProcedureReturn 
EndProcedure   
Post Reply