{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
module Data.Bit.PdepPext
( pdep
, pext
) where
#if MIN_VERSION_base(4,11,0)
import GHC.Exts
pdep :: Word -> Word -> Word
pdep (W# src#) (W# mask#) = W# (pdep# src# mask#)
pext :: Word -> Word -> Word
pext (W# src#) (W# mask#) = W# (pext# src# mask#)
#else
import Data.Bits
pdep :: Word -> Word -> Word
pdep = go 0
where
go :: Word -> Word -> Word -> Word
go result _ 0 = result
go result src mask = go newResult newSrc newMask
where
lowest = 1 `shiftL` countTrailingZeros mask
newResult = if src .&. 1 == 0 then result else result .|. lowest
newSrc = src `shiftR` 1
newMask = mask .&. complement lowest
pext :: Word -> Word -> Word
pext src mask = loop 0 0 0
where
loop i count acc
| i >= finiteBitSize (0 :: Word)
= acc
| testBit mask i
= loop (i + 1) (count + 1) (if testBit src i then setBit acc count else acc)
| otherwise
= loop (i + 1) count acc
#endif