@@ -1831,6 +1831,10 @@ powerSet :: Set a -> Set (Set a)
1831
1831
powerSet xs =
1832
1832
let ! w = length xs
1833
1833
! 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])]
1834
1838
! v = generateA (0 , 2 ^ w - 1 ) $ \ m ->
1835
1839
if m == 0
1836
1840
then Tip
@@ -1840,26 +1844,34 @@ powerSet xs =
1840
1844
make ! begin ! s =
1841
1845
if s == 0 then Tip
1842
1846
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))
1844
1849
(make begin sl)
1845
1850
(make (begin + sl+ 1 ) sr)
1846
1851
in make 0 (2 ^ w)
1847
1852
1848
1853
generateA :: A. Ix i => (i ,i ) -> (i -> a ) -> A. Array i a
1849
1854
generateA bnd f = A. listArray bnd $ fmap f $ A. range bnd
1850
1855
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
1863
1875
1864
1876
data StrictTriple = ST ! Int ! Int ! Int
1865
1877
0 commit comments