hw-prim-bits 0.1.0.2 → 0.1.0.3
raw patch · 6 files changed
+114/−1 lines, 6 files
Files
- cbits/bits.c +66/−0
- hw-prim-bits.cabal +1/−1
- src/HaskellWorks/Prim/Bits.hs +11/−0
- src/HaskellWorks/Prim/Bits/Fast.hs +14/−0
- src/HaskellWorks/Prim/Bits/Slow.hs +14/−0
- test/HaskellWorks/Prim/BitsSpec.hs +8/−0
cbits/bits.c view
@@ -19,6 +19,7 @@ uint32_t result = 0; while (1) {+ // Mask out all but the lowest bit const uint32_t lowest = (-mask & mask); if (lowest == 0) {@@ -54,6 +55,7 @@ uint64_t result = 0; while (1) {+ // Mask out all but the lowest bit const uint64_t lowest = (-mask & mask); if (lowest == 0) {@@ -65,6 +67,70 @@ result |= lsb & lowest; mask &= ~lowest; src >>= 1;+ }++ return result;+}++uint32_t fast_pext32(+ uint32_t src,+ uint32_t mask) {+ uint32_t result;++ __asm__ __volatile__("pextl %%ecx,%%ebx,%%eax"+ :"=a"(result)+ :"a"(result), "b"(src), "c"(mask)+ );++ return result;+}++uint32_t slow_pext32(+ uint32_t src,+ uint32_t mask) {+ uint32_t result = 0;+ int offset = 0;++ for (int bit = 0; bit != sizeof(uint32_t) * 8; ++bit) {+ const uint32_t src_bit = (src >> bit) & 1;+ const uint32_t mask_bit = (mask >> bit) & 1;++ if (mask_bit) {+ result |= (uint32_t)(src_bit) << offset;+ ++offset;+ }+ }++ return result;+}++uint64_t fast_pext64(+ uint64_t src,+ uint64_t mask) {+ uint64_t result;++ __asm__ __volatile__("pextq %%rcx,%%rbx,%%rax"+ :"=a"(result)+ :"a"(result), "b"(src), "c"(mask)+ );++ return result;+}++uint64_t slow_pext64(+ uint64_t src,+ uint64_t mask) {+ uint64_t result = 0;+ int offset = 0;++ for (int bit = 0; bit != sizeof(uint64_t) * 8; ++bit) {+ const uint64_t src_bit = (src >> bit) & 1;+ const uint64_t mask_bit = (mask >> bit) & 1;++ if (mask_bit) {+ result |= (uint64_t)(src_bit) << offset;+ ++offset;+ } } return result;
hw-prim-bits.cabal view
@@ -1,5 +1,5 @@ name: hw-prim-bits-version: 0.1.0.2+version: 0.1.0.3 synopsis: Primitive support for bit manipulation description: Please see README.md homepage: https://github.com/githubuser/hw-prim-bits#readme
src/HaskellWorks/Prim/Bits.hs view
@@ -15,3 +15,14 @@ instance Pdep Word32 where pdep = pdep32 {-# INLINE pdep #-}++class Pext a where+ pext :: a -> a -> a++instance Pext Word64 where+ pext = pext64+ {-# INLINE pext #-}++instance Pext Word32 where+ pext = pext32+ {-# INLINE pext #-}
src/HaskellWorks/Prim/Bits/Fast.hs view
@@ -1,6 +1,8 @@ module HaskellWorks.Prim.Bits.Fast ( pdep64 , pdep32+ , pext64+ , pext32 ) where import Data.Word@@ -16,3 +18,15 @@ pdep32 :: Word32 -> Word32 -> Word32 pdep32 = fast_pdep32 {-# INLINE pdep32 #-}++foreign import ccall unsafe "bits.h" fast_pext64 :: Word64 -> Word64 -> Word64++pext64 :: Word64 -> Word64 -> Word64+pext64 = fast_pext64+{-# INLINE pext64 #-}++foreign import ccall unsafe "bits.h" fast_pext32 :: Word32 -> Word32 -> Word32++pext32 :: Word32 -> Word32 -> Word32+pext32 = fast_pext32+{-# INLINE pext32 #-}
src/HaskellWorks/Prim/Bits/Slow.hs view
@@ -1,6 +1,8 @@ module HaskellWorks.Prim.Bits.Slow ( pdep64 , pdep32+ , pext64+ , pext32 ) where import Data.Word@@ -16,3 +18,15 @@ pdep32 :: Word32 -> Word32 -> Word32 pdep32 = slow_pdep32 {-# INLINE pdep32 #-}++foreign import ccall unsafe "bits.h" slow_pext64 :: Word64 -> Word64 -> Word64++pext64 :: Word64 -> Word64 -> Word64+pext64 = slow_pext64+{-# INLINE pext64 #-}++foreign import ccall unsafe "bits.h" slow_pext32 :: Word32 -> Word32 -> Word32++pext32 :: Word32 -> Word32 -> Word32+pext32 = slow_pext32+{-# INLINE pext32 #-}
test/HaskellWorks/Prim/BitsSpec.hs view
@@ -22,3 +22,11 @@ a <- forAll $ G.word32 R.constantBounded b <- forAll $ G.word32 R.constantBounded S.pdep32 a b === F.pdep32 a b+ it "pext64 behaves the same" $ require $ property $ do+ a <- forAll $ G.word64 R.constantBounded+ b <- forAll $ G.word64 R.constantBounded+ S.pext64 a b === F.pext64 a b+ it "pext32 behaves the same" $ require $ property $ do+ a <- forAll $ G.word32 R.constantBounded+ b <- forAll $ G.word32 R.constantBounded+ S.pext32 a b === F.pext32 a b