Fastest way to find a long's MSB?
Phil Pilgrim (PhiPi)
Posts: 23,514
I'm working on a program that requires a very fast log2 computation. The "exponent" part of the result is the position of the input number's most-significant bit. Here's the code I came up with to find that bit quickly:
Is there a faster way?
-Phil
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
VAR
long number, exponent
OBJ
pst : "Parallax Serial Terminal"
rnd : "RealRandom"
PUB start | seed, x
pst.start(9600)
rnd.start
seed := rnd.random
cognew(@msb, @number)
repeat 100
number := x := ?seed & ?seed & ?seed
repeat while number
pst.bin(x, 32)
pst.char(" ")
pst.dec(exponent)
pst.char(13)
DAT
msb mov result_addr,par
add result_addr,#4
main_lp rdlong acc,par wz
if_z jmp #main_lp
'-------[ Begin ]--------------------------------------------------------------
rev acc,#0
neg accx,acc
and accx,acc
test accx,_0x0000ffff wc
muxc exp,#16
test accx,_0x00ff00ff wc
muxc exp,#8
test accx,_0x0f0f0f0f wc
muxc exp,#4
test accx,_0x33333333 wc
muxc exp,#2
test accx,_0x55555555 wc
muxc exp,#1 ' 13 instructions.
'-------[ End ]----------------------------------------------------------------
wrlong exp,result_addr
wrlong zero,par
jmp #main_lp
exp long 0
_0x0000ffff long $0000_ffff
_0x00ff00ff long $00ff_00ff
_0x0f0f0f0f long $0f0f_0f0f
_0x33333333 long $3333_3333
_0x55555555 long $5555_5555
zero long 0
acc res 1
accx res 1
result_addr res 1
Is there a faster way?
-Phil

Comments
Do you happen to know how the >| operator does it?
No, I don't. I've never examined the pcode interpreter. But I imagine that space took precedence over time for the more obscure operators.
BTW, I've come to realize that the solution to the stated challenge won't meet my objectives anyway. My overall objective is to compute log(x) for x == 1 .. 1023, normalized to 255 for log(1023). The ROM table lookup won't do that without a post-multiply. (It has to do with compressing the dynamic range of the Prop BOE's 10-bit ADC.)
-Phil