Skip to content

Commit e4e9fd3

Browse files
committed
explanation, and better name, for helper function bit_pattern
1 parent 2d12c48 commit e4e9fd3

File tree

1 file changed

+25
-13
lines changed

1 file changed

+25
-13
lines changed

containers/src/Data/Set/Internal.hs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,6 +1831,10 @@ powerSet :: Set a -> Set (Set a)
18311831
powerSet xs =
18321832
let !w = length xs
18331833
!u = A.listArray (0, w-1) $ toList xs
1834+
-- v ! m is the set with bit pattern m,
1835+
-- e.g., for xs = [1,2,3],
1836+
-- we have fmap Foldable.toList v = array (0,7)
1837+
-- [(0,[]),(1,[3]),(2,[2]),(3,[2,3]),(4,[1]),(5,[1,3]),(6,[1,2]),(7,[1,2,3])]
18341838
!v = generateA (0, 2^w -1) $ \ m ->
18351839
if m == 0
18361840
then Tip
@@ -1840,26 +1844,34 @@ powerSet xs =
18401844
make !begin !s =
18411845
if s == 0 then Tip
18421846
else let !sl = div (s-1) 2; !sr = s - 1 - sl
1843-
in bin (v A.! forw w (begin + sl))
1847+
-- @bit_pattern@ puts sets in lexicographic order
1848+
in bin (v A.! bit_pattern w (begin + sl))
18441849
(make begin sl)
18451850
(make (begin + sl+1) sr)
18461851
in make 0 (2^w)
18471852

18481853
generateA :: A.Ix i => (i,i) -> (i -> a) -> A.Array i a
18491854
generateA bnd f = A.listArray bnd $ fmap f $ A.range bnd
18501855

1851-
forw :: Int -> Int -> Int
1852-
forw 0 _ = 0
1853-
forw !width !n = fr_go_branch (bit $ width-1) n 0
1854-
1855-
fr_go_branch :: Int -> Int -> Int -> Int
1856-
fr_go_branch !topmask !n !set =
1857-
if n == 0 then set
1858-
else if 0 == ((n-1) .&. topmask)
1859-
then fr_go_branch (shiftR topmask 1)
1860-
(n-1) (set .|. topmask)
1861-
else fr_go_branch (shiftR topmask 1)
1862-
(n .&. complement topmask) set
1856+
-- | @bit_pattern w i@ is the bit pattern at position i
1857+
-- in the lexicographic enumeration of their meanings as sets.
1858+
-- map (bit_pattern 3) [0..7]
1859+
-- = [0,4,6,7,5,2,3,1]
1860+
-- = [000,100,110,111,101,010,011,001]
1861+
-- This function is called often. It takes 1/3 of run-time,
1862+
-- but it does not allocate.
1863+
bit_pattern :: Int -> Int -> Int
1864+
bit_pattern 0 _ = 0
1865+
bit_pattern !width !i =
1866+
let go :: Int -> Int -> Int -> Int
1867+
go !topmask !n !set =
1868+
if n == 0 then set
1869+
else if 0 == ((n-1) .&. topmask)
1870+
then go (shiftR topmask 1)
1871+
(n-1) (set .|. topmask)
1872+
else go (shiftR topmask 1)
1873+
(n .&. complement topmask) set
1874+
in go (bit $ width-1) i 0
18631875

18641876
data StrictTriple = ST !Int !Int !Int
18651877

0 commit comments

Comments
 (0)