{-# LANGUAGE BangPatterns, CPP, MagicHash #-} module Main ( main ) where import Data.Bits import GHC.Prim import GHC.Word #include "MachDeps.h" main = putStr (test_popCnt ++ "\n" ++ test_popCnt8 ++ "\n" ++ test_popCnt16 ++ "\n" ++ test_popCnt32 ++ "\n" ++ test_popCnt64 ++ "\n" ++ "\n" ) popcnt :: Word -> Word popcnt (W# w#) = W# (popCnt# w#) popcnt8 :: Word -> Word popcnt8 (W# w#) = W# (popCnt8# w#) popcnt16 :: Word -> Word popcnt16 (W# w#) = W# (popCnt16# w#) popcnt32 :: Word -> Word popcnt32 (W# w#) = W# (popCnt32# w#) popcnt64 :: Word64 -> Word popcnt64 (W64# w#) = #if SIZEOF_HSWORD == 4 W# (popCnt64# w#) #else W# (popCnt# w#) #endif -- Cribbed from https://gitlab.haskell.org/ghc/ghc/issues/3563 slowPopcnt :: Word -> Word slowPopcnt x = count' (bitSize x) x 0 where count' 0 _ !acc = acc count' n x acc = count' (n-1) (x `shiftR` 1) (acc + if x .&. 1 == 1 then 1 else 0) test_popCnt = test popcnt slowPopcnt test_popCnt8 = test popcnt8 (slowPopcnt . fromIntegral . (mask 8 .&.)) test_popCnt16 = test popcnt16 (slowPopcnt . fromIntegral . (mask 16 .&.)) test_popCnt32 = test popcnt32 (slowPopcnt . fromIntegral . (mask 32 .&.)) test_popCnt64 = test popcnt64 (slowPopcnt . fromIntegral . (mask 64 .&.)) mask n = (2 ^ n) - 1 test :: (Show a, Num a) => (a -> Word) -> (a -> Word) -> String test fast slow = case failing of [] -> "OK" ((_, e, a, i):xs) -> "FAIL\n" ++ " Input: " ++ show i ++ "\nExpected: " ++ show e ++ "\n Actual: " ++ show a where failing = dropWhile ( \(b,_,_,_) -> b) . map (\ x -> (slow x == fast x, slow x, fast x, x)) $ cases expected = map slow cases actual = map fast cases -- 10 random numbers #if SIZEOF_HSWORD == 4 cases = [1480294021,1626858410,2316287658,1246556957,3806579062,65945563, 1521588071,791321966,1355466914,2284998160] #elif SIZEOF_HSWORD == 8 cases = [11004539497957619752,5625461252166958202,1799960778872209546, 16979826074020750638,12789915432197771481,11680809699809094550, 13208678822802632247,13794454868797172383,13364728999716654549, 17516539991479925226] #else # error Unexpected word size #endif