{-# LANGUAGE MagicHash #-} {-# LANGUAGE UnliftedFFITypes #-} module Data.Bit.SIMD ( ompPopcount , ompCom , ompAnd , ompIor , ompXor , ompAndn , ompIorn , ompNand , ompNior , ompXnor , reverseBitsC , bitIndexC , nthBitIndexC , selectBitsC ) where import Control.Monad.ST import Control.Monad.ST.Unsafe (unsafeIOToST) import Data.Primitive.ByteArray import GHC.Exts foreign import ccall unsafe "_hs_bitvec_popcount" omp_popcount :: ByteArray# -> Int# -> Int# -- | SIMD optimized popcount. The length is in 32 bit words. ompPopcount :: ByteArray -> Int -> Int ompPopcount (ByteArray arg#) (I# len#) = I# (omp_popcount arg# len#) {-# INLINE ompPopcount #-} foreign import ccall unsafe "_hs_bitvec_com" omp_com :: MutableByteArray# s -> ByteArray# -> Int# -> IO () -- | SIMD optimized bitwise complement. The length is in bytes -- and the result array should have at least that many bytes. ompCom :: MutableByteArray s -> ByteArray -> Int -> ST s () ompCom (MutableByteArray res#) (ByteArray arg#) (I# len#) = unsafeIOToST (omp_com res# arg# len#) {-# INLINE ompCom #-} foreign import ccall unsafe "_hs_bitvec_and" omp_and :: MutableByteArray# s -> ByteArray# -> ByteArray# -> Int# -> IO () -- | SIMD optimized bitwise AND. The length is in bytes -- and the result array should have at least that many bytes. ompAnd :: MutableByteArray s -> ByteArray -> ByteArray -> Int -> ST s () ompAnd (MutableByteArray res#) (ByteArray arg1#) (ByteArray arg2#) (I# len#) = unsafeIOToST (omp_and res# arg1# arg2# len#) {-# INLINE ompAnd #-} foreign import ccall unsafe "_hs_bitvec_ior" omp_ior :: MutableByteArray# s -> ByteArray# -> ByteArray# -> Int# -> IO () -- | SIMD optimized bitwise OR. The length is in bytes -- and the result array should have at least that many bytes. ompIor :: MutableByteArray s -> ByteArray -> ByteArray -> Int -> ST s () ompIor (MutableByteArray res#) (ByteArray arg1#) (ByteArray arg2#) (I# len#) = unsafeIOToST (omp_ior res# arg1# arg2# len#) {-# INLINE ompIor #-} foreign import ccall unsafe "_hs_bitvec_xor" omp_xor :: MutableByteArray# s -> ByteArray# -> ByteArray# -> Int# -> IO () -- | SIMD optimized bitwise XOR. The length is in bytes -- and the result array should have at least that many bytes. ompXor :: MutableByteArray s -> ByteArray -> ByteArray -> Int -> ST s () ompXor (MutableByteArray res#) (ByteArray arg1#) (ByteArray arg2#) (I# len#) = unsafeIOToST (omp_xor res# arg1# arg2# len#) {-# INLINE ompXor #-} foreign import ccall unsafe "_hs_bitvec_andn" omp_andn :: MutableByteArray# s -> ByteArray# -> ByteArray# -> Int# -> IO () -- | SIMD optimized bitwise AND with the second argument inverted. The length is in bytes -- and the result array should have at least that many bytes. ompAndn :: MutableByteArray s -> ByteArray -> ByteArray -> Int -> ST s () ompAndn (MutableByteArray res#) (ByteArray arg1#) (ByteArray arg2#) (I# len#) = unsafeIOToST (omp_andn res# arg1# arg2# len#) {-# INLINE ompAndn #-} foreign import ccall unsafe "_hs_bitvec_iorn" omp_iorn :: MutableByteArray# s -> ByteArray# -> ByteArray# -> Int# -> IO () -- | SIMD optimized bitwise OR with the second argument inverted. The length is in bytes -- and the result array should have at least that many bytes. ompIorn :: MutableByteArray s -> ByteArray -> ByteArray -> Int -> ST s () ompIorn (MutableByteArray res#) (ByteArray arg1#) (ByteArray arg2#) (I# len#) = unsafeIOToST (omp_iorn res# arg1# arg2# len#) {-# INLINE ompIorn #-} foreign import ccall unsafe "_hs_bitvec_nand" omp_nand :: MutableByteArray# s -> ByteArray# -> ByteArray# -> Int# -> IO () -- | SIMD optimized bitwise NAND. The length is in bytes -- and the result array should have at least that many bytes. ompNand :: MutableByteArray s -> ByteArray -> ByteArray -> Int -> ST s () ompNand (MutableByteArray res#) (ByteArray arg1#) (ByteArray arg2#) (I# len#) = unsafeIOToST (omp_nand res# arg1# arg2# len#) {-# INLINE ompNand #-} foreign import ccall unsafe "_hs_bitvec_nior" omp_nior :: MutableByteArray# s -> ByteArray# -> ByteArray# -> Int# -> IO () -- | SIMD optimized bitwise NOR. The length is in bytes -- and the result array should have at least that many bytes. ompNior :: MutableByteArray s -> ByteArray -> ByteArray -> Int -> ST s () ompNior (MutableByteArray res#) (ByteArray arg1#) (ByteArray arg2#) (I# len#) = unsafeIOToST (omp_nior res# arg1# arg2# len#) {-# INLINE ompNior #-} foreign import ccall unsafe "_hs_bitvec_xnor" omp_xnor :: MutableByteArray# s -> ByteArray# -> ByteArray# -> Int# -> IO () -- | SIMD optimized bitwise XNOR. The length is in bytes -- and the result array should have at least that many bytes. ompXnor :: MutableByteArray s -> ByteArray -> ByteArray -> Int -> ST s () ompXnor (MutableByteArray res#) (ByteArray arg1#) (ByteArray arg2#) (I# len#) = unsafeIOToST (omp_xnor res# arg1# arg2# len#) {-# INLINE ompXnor #-} foreign import ccall unsafe "_hs_bitvec_reverse_bits" reverse_bits :: MutableByteArray# s -> ByteArray# -> Int# -> IO () -- | The length is in words. reverseBitsC :: MutableByteArray s -> ByteArray -> Int -> ST s () reverseBitsC (MutableByteArray res#) (ByteArray arg#) (I# len#) = unsafeIOToST (reverse_bits res# arg# len#) {-# INLINE reverseBitsC #-} foreign import ccall unsafe "_hs_bitvec_bit_index" bit_index :: ByteArray# -> Int# -> Bool -> Int# bitIndexC :: ByteArray -> Int -> Bool -> Int bitIndexC (ByteArray arg#) (I# len#) bit = I# (bit_index arg# len# bit) {-# INLINE bitIndexC #-} foreign import ccall unsafe "_hs_bitvec_nth_bit_index" nth_bit_index :: ByteArray# -> Int# -> Bool -> Int# -> Int# nthBitIndexC :: ByteArray -> Int -> Bool -> Int -> Int nthBitIndexC (ByteArray arg#) (I# len#) bit (I# n#) = I# (nth_bit_index arg# len# bit n#) {-# INLINE nthBitIndexC #-} foreign import ccall unsafe "_hs_bitvec_select_bits" select_bits_c :: MutableByteArray# s -> ByteArray# -> ByteArray# -> Int# -> Bool -> IO Int selectBitsC :: MutableByteArray s -> ByteArray -> ByteArray -> Int -> Bool -> ST s Int selectBitsC (MutableByteArray res#) (ByteArray arg1#) (ByteArray arg2#) (I# len#) exclude = unsafeIOToST (select_bits_c res# arg1# arg2# len# exclude) {-# INLINE selectBitsC #-}