[Haskell-cafe] Understanding allocation behavior
Robert Dockins
robdockins at fastmail.fm
Sat Apr 8 18:54:58 EDT 2006
On Apr 8, 2006, at 1:58 PM, David F. Place wrote:
> Thanks Bulat and Robert. I implemented Bulat's idea as the
> following. It tests faster than Roberts. I use Robert's to
> compute the table. The performance seems satisfactory now.
>
> size :: Set a -> Int
> size (Set w) = countBits w
> where
> countBits w
> | w == 0 = 0
> | otherwise = countBits (w `shiftR` 8) + bitsTable!(w .&.
> 0xFF)
>
> bitsTable :: Array Word Int
> bitsTable = array (0,255) $ [(i,bitcount i) | i <- [0..255]]
>
> bitcount :: Word -> Int
> bitcount 0 = 0
> bitcount x = 1 + bitcount (x .&. (x-1))
There's a couple of other nice bit-twiddily things you can do:
countBits :: Word -> Int
countBits w
| w == 0 = 0
| otherwise = countBits (w `shiftR` 8) + bitsTable!(w .&. 0xFF)
bitsTable :: Array Word Int
bitsTable = array (0,255) $ [(i,bitcount i) | i <- [0..255]]
bitcount :: Word -> Int
bitcount 0 = 0
bitcount x = 1 + bitcount (x .&. (x-1))
lsb :: Word -> Int
lsb x = countBits ((x-1) .&. (complement x))
-- stolen from http://aggregate.org/MAGIC/
msb :: Word -> Int
msb x0 = let
x1 = x0 .|. (x0 `shiftR` 1)
x2 = x1 .|. (x1 `shiftR` 2)
x3 = x2 .|. (x2 `shiftR` 4)
x4 = x3 .|. (x3 `shiftR` 8)
x5 = x4 .|. (x4 `shiftR` 16)
in countBits x5 - 1
findMinIndex :: Word -> Int
findMinIndex 0 =
error "EnumSet.findMin: empty set has no minimal element"
findMinIndex w = lsb w
findMaxIndex :: Word -> Int
findMaxIndex 0 =
error "EnumSet.findMax: empty set has no maximal element"
findMaxIndex w = msb w
Which should make all access to the greatest or least element O(1).
I guess, come to think of it, all operations on EnumSet are O(1) by
virtue of the set size being upper-bounded. At any rate this turns
recursion into unboxable straight-line code and I think it does less
allocations.
Rob Dockins
Speak softly and drive a Sherman tank.
Laugh hard; it's a long way to the bank.
-- TMBG
More information about the Haskell-Cafe
mailing list