diff --git a/hw-bits.cabal b/hw-bits.cabal
--- a/hw-bits.cabal
+++ b/hw-bits.cabal
@@ -1,7 +1,7 @@
 cabal-version:  2.2
 
 name:                   hw-bits
-version:                0.7.1.1
+version:                0.7.1.2
 synopsis:               Bit manipulation
 description:            Please see README.md
 category:               Data, Bit
@@ -71,6 +71,11 @@
                         HaskellWorks.Data.Bits.BitShown
                         HaskellWorks.Data.Bits.BitWise
                         HaskellWorks.Data.Bits.Broadword
+                        HaskellWorks.Data.Bits.Broadword.Type
+                        HaskellWorks.Data.Bits.Broadword.Word8
+                        HaskellWorks.Data.Bits.Broadword.Word16
+                        HaskellWorks.Data.Bits.Broadword.Word32
+                        HaskellWorks.Data.Bits.Broadword.Word64
                         HaskellWorks.Data.Bits.ElemFixedBitSize
                         HaskellWorks.Data.Bits.FixedBitSize
                         HaskellWorks.Data.Bits.FromBitTextByteString
@@ -82,6 +87,7 @@
                         HaskellWorks.Data.Bits.Types.Broadword
                         HaskellWorks.Data.Bits.Types.Builtin
                         HaskellWorks.Data.Bits.Word
+                        HaskellWorks.Data.Bits.Word64
                         HaskellWorks.Data.Bits.Writer.Storable
   other-modules:        Paths_hw_bits
   autogen-modules:      Paths_hw_bits
diff --git a/src/HaskellWorks/Data/Bits/Broadword.hs b/src/HaskellWorks/Data/Bits/Broadword.hs
--- a/src/HaskellWorks/Data/Bits/Broadword.hs
+++ b/src/HaskellWorks/Data/Bits/Broadword.hs
@@ -7,132 +7,17 @@
 {-# LANGUAGE TypeFamilies          #-}
 
 module HaskellWorks.Data.Bits.Broadword
-  ( Broadword(..)
-  , broadword
-  , h
-  , l
-  , lsb
-  , kBitDiff
-  , kBitDiffPos
-  , kBitDiffUnsafe
+  {-# DEPRECATED "Import the relevant module instead" #-}
+  ( BW.Broadword(..)
+  , BW.broadword
+  , W64.lsb
+  , W64.h
+  , W64.l
+  , W64.kBitDiff
+  , W64.kBitDiffPos
+  , W64.kBitDiffUnsafe
   ) where
 
-import Control.DeepSeq
-import Data.Word
-import GHC.Generics
-import HaskellWorks.Data.Bits.BitWise
-
-import qualified Data.Bits as DB
-
-newtype Broadword a = Broadword a deriving (Eq, Show, Generic, NFData)
-
-broadword :: Broadword Word64 -> Word64
-broadword (Broadword a) = a
-{-# INLINE broadword #-}
-
--- | Initialise all sub-words of size k where 'k' ∈ { 2, 4, 8, 16, 32, 64 } such that the lowest bit is set to 1 and all other bits are cleared.
---
--- >>> import Numeric(showHex)
--- >>> showHex (l 2) ""
--- "5555555555555555"
--- >>> showHex (l 4) ""
--- "1111111111111111"
--- >>> showHex (l 8) ""
--- "101010101010101"
--- >>> showHex (l 16) ""
--- "1000100010001"
--- >>> showHex (l 32) ""
--- "100000001"
--- >>> showHex (l 64) ""
--- "1"
-l :: Int -> Word64
-l 2  = 0x5555555555555555
-l 4  = 0x1111111111111111
-l 8  = 0x0101010101010101
-l 16 = 0x0001000100010001
-l 32 = 0x0000000100000001
-l 64 = 0x0000000000000001
-l k  = error ("Invalid h k where k = " ++ show k)
-{-# INLINE l #-}
-
--- | Initialise all sub-words of size k where 'k' ∈ { 2, 4, 8, 16, 32, 64 } such that the highest bit is set to 1 and all other bits are cleared.
---
--- >>> import Numeric(showHex)
--- >>> showHex (h 2) ""
--- "aaaaaaaaaaaaaaaa"
--- >>> showHex (h 4) ""
--- "8888888888888888"
--- >>> showHex (h 8) ""
--- "8080808080808080"
--- >>> showHex (h 16) ""
--- "8000800080008000"
--- >>> showHex (h 32) ""
--- "8000000080000000"
--- >>> showHex (h 64) ""
--- "8000000000000000"
-h :: Int -> Word64
-h 2  = 0xaaaaaaaaaaaaaaaa
-h 4  = 0x8888888888888888
-h 8  = 0x8080808080808080
-h 16 = 0x8000800080008000
-h 32 = 0x8000000080000000
-h 64 = 0x8000000000000000
-h k  = error ("Invalid h k where k = " ++ show k)
-{-# INLINE h #-}
-
--- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8, 16, 32, 64 }.
---
--- The subtraction respects 2's complement so sub-words may be regarded as signed or unsigned words.
---
--- >>> import Numeric(showHex)
--- >>> showHex (kBitDiff 8 0x0807060504030201 0x0404030302020101) ""
--- "403030202010100"
--- >>> showHex (kBitDiff 8 0x0807060504030201 0x0102030405060708) ""
--- "7050301fffdfbf9"
--- >>> showHex (kBitDiff 8 0x20000000000000ff 0x10000000000000ff) ""
--- "1000000000000000"
-kBitDiff :: Int -> Word64 -> Word64 -> Word64
-kBitDiff k x y = ((x .|. h k) - (y .&. comp (h k))) .^. ((x .^. comp y) .&. h k)
-{-# INLINE kBitDiff #-}
-
--- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8, 16, 32, 64 } where results are bounded from below by 0.
---
--- >>> import Numeric(showHex)
--- >>> showHex (kBitDiffPos 8 0x0807060504030201 0x0404030302020101) ""
--- "403030202010100"
--- >>> showHex (kBitDiffPos 8 0x0807060504030201 0x0102030405060708) ""
--- "705030100000000"
--- >>> showHex (kBitDiffPos 8 0x20000000000000ff 0x10000000000000ff) ""
--- "1000000000000000"
-kBitDiffPos :: Int -> Word64 -> Word64 -> Word64
-kBitDiffPos k x y = let d = kBitDiff k x y in d .&. kBitDiff k 0 ((comp d .&. h 8) .>. fromIntegral (k - 1))
-{-# INLINE kBitDiffPos #-}
-
--- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8, 16, 32, 64 } where all the sub-words of 'x' and 'y' must
--- not have the signed bit set for the result to be meaningful.
---
--- >>> import Numeric(showHex)
--- >>> showHex (kBitDiffUnsafe 8 0x0807060504030201 0x0404030302020101) ""
--- "403030202010100"
--- >>> showHex (kBitDiffUnsafe 8 0x0807060504030201 0x0102030405060708) ""
--- "7050301fffdfbf9"
--- >>> showHex (kBitDiffUnsafe 8 0x20000000000000ff 0x10000000000000ff) ""
--- "1000000000000080"
-kBitDiffUnsafe :: Int -> Word64 -> Word64 -> Word64
-kBitDiffUnsafe k x y = ((x .|. h k) - y) .^. h k
-{-# INLINE kBitDiffUnsafe #-}
-
--- | Returns the position of the least significant bit (0-based).
---
--- This is equivalent to 'DB.countTrailingZeros' except for when there are no bits set.  In which case
--- return a word with all bits set.
---
--- >>> lsb 8
--- 3
--- >>> lsb 1
--- 0
--- >>> lsb 0
--- 18446744073709551615
-lsb :: Word64 -> Word64
-lsb w = let r = fromIntegral (DB.countTrailingZeros w) in r .|. negate ((r .>. 6) .&. 0x1)
-{-# INLINE lsb #-}
+import qualified HaskellWorks.Data.Bits.Broadword.Type   as BW
+import qualified HaskellWorks.Data.Bits.Broadword.Word64 as W64
+import qualified HaskellWorks.Data.Bits.Word64           as W64
diff --git a/src/HaskellWorks/Data/Bits/Broadword/Type.hs b/src/HaskellWorks/Data/Bits/Broadword/Type.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Bits/Broadword/Type.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveFunctor         #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+module HaskellWorks.Data.Bits.Broadword.Type
+  ( Broadword(..)
+  , broadword
+  ) where
+
+import Control.DeepSeq
+import Data.Word
+import GHC.Generics
+
+newtype Broadword a = Broadword a deriving (Eq, Show, Functor, Generic, NFData)
+
+broadword :: Broadword Word64 -> Word64
+broadword (Broadword a) = a
+{-# INLINE broadword #-}
diff --git a/src/HaskellWorks/Data/Bits/Broadword/Word16.hs b/src/HaskellWorks/Data/Bits/Broadword/Word16.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Bits/Broadword/Word16.hs
@@ -0,0 +1,95 @@
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+module HaskellWorks.Data.Bits.Broadword.Word16
+  ( h
+  , l
+  , kBitDiff
+  , kBitDiffPos
+  , kBitDiffUnsafe
+  ) where
+
+import Data.Word
+import HaskellWorks.Data.Bits.BitWise
+
+-- | Initialise all sub-words of size k where 'k' ∈ { 2, 4, 8, 16 } such that the lowest bit is set to 1 and all other bits are cleared.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (l 2) ""
+-- "5555"
+-- >>> showHex (l 4) ""
+-- "1111"
+-- >>> showHex (l 8) ""
+-- "101"
+-- >>> showHex (l 16) ""
+-- "1"
+l :: Int -> Word16
+l 2  = 0x5555
+l 4  = 0x1111
+l 8  = 0x0101
+l 16 = 0x0001
+l k  = error ("Invalid h k where k = " ++ show k)
+{-# INLINE l #-}
+
+-- | Initialise all sub-words of size k where 'k' ∈ { 2, 4, 8, 16 } such that the highest bit is set to 1 and all other bits are cleared.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (h 2) ""
+-- "aaaa"
+-- >>> showHex (h 4) ""
+-- "8888"
+-- >>> showHex (h 8) ""
+-- "8080"
+-- >>> showHex (h 16) ""
+-- "8000"
+h :: Int -> Word16
+h 2  = 0xaaaa
+h 4  = 0x8888
+h 8  = 0x8080
+h 16 = 0x8000
+h k  = error ("Invalid h k where k = " ++ show k)
+{-# INLINE h #-}
+
+-- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8, 16 }.
+--
+-- The subtraction respects 2's complement so sub-words may be regarded as signed or unsigned words.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (kBitDiff 8 0x0201 0x0101) ""
+-- "100"
+-- >>> showHex (kBitDiff 8 0x0201 0x0102) ""
+-- "1ff"
+-- >>> showHex (kBitDiff 8 0x20ff 0x10ff) ""
+-- "1000"
+kBitDiff :: Int -> Word16 -> Word16 -> Word16
+kBitDiff k x y = ((x .|. h k) - (y .&. comp (h k))) .^. ((x .^. comp y) .&. h k)
+{-# INLINE kBitDiff #-}
+
+-- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8, 16 } where results are bounded from below by 0.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (kBitDiffPos 8 0x0201 0x0101) ""
+-- "100"
+-- >>> showHex (kBitDiffPos 8 0x0201 0x0102) ""
+-- "100"
+-- >>> showHex (kBitDiffPos 8 0x20ff 0x10ff) ""
+-- "1000"
+kBitDiffPos :: Int -> Word16 -> Word16 -> Word16
+kBitDiffPos k x y = let d = kBitDiff k x y in d .&. kBitDiff k 0 ((comp d .&. h 8) .>. fromIntegral (k - 1))
+{-# INLINE kBitDiffPos #-}
+
+-- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8, 16, 32, 64 } where all the sub-words of 'x' and 'y' must
+-- not have the signed bit set for the result to be meaningful.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (kBitDiffUnsafe 8 0x0201 0x0101) ""
+-- "100"
+-- >>> showHex (kBitDiffUnsafe 8 0x0201 0x0102) ""
+-- "1ff"
+-- >>> showHex (kBitDiffUnsafe 8 0x20ff 0x10ff) "" -- produces nonsense in the last sub-word
+-- "1080"
+kBitDiffUnsafe :: Int -> Word16 -> Word16 -> Word16
+kBitDiffUnsafe k x y = ((x .|. h k) - y) .^. h k
+{-# INLINE kBitDiffUnsafe #-}
diff --git a/src/HaskellWorks/Data/Bits/Broadword/Word32.hs b/src/HaskellWorks/Data/Bits/Broadword/Word32.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Bits/Broadword/Word32.hs
@@ -0,0 +1,101 @@
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+module HaskellWorks.Data.Bits.Broadword.Word32
+  ( h
+  , l
+  , kBitDiff
+  , kBitDiffPos
+  , kBitDiffUnsafe
+  ) where
+
+import Data.Word
+import HaskellWorks.Data.Bits.BitWise
+
+-- | Initialise all sub-words of size k where 'k' ∈ { 2, 4, 8, 16, 32 } such that the lowest bit is set to 1 and all other bits are cleared.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (l 2) ""
+-- "55555555"
+-- >>> showHex (l 4) ""
+-- "11111111"
+-- >>> showHex (l 8) ""
+-- "1010101"
+-- >>> showHex (l 16) ""
+-- "10001"
+-- >>> showHex (l 32) ""
+-- "1"
+l :: Int -> Word32
+l 2  = 0x55555555
+l 4  = 0x11111111
+l 8  = 0x01010101
+l 16 = 0x00010001
+l 32 = 0x00000001
+l k  = error ("Invalid h k where k = " ++ show k)
+{-# INLINE l #-}
+
+-- | Initialise all sub-words of size k where 'k' ∈ { 2, 4, 8, 16, 32 } such that the highest bit is set to 1 and all other bits are cleared.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (h 2) ""
+-- "aaaaaaaa"
+-- >>> showHex (h 4) ""
+-- "88888888"
+-- >>> showHex (h 8) ""
+-- "80808080"
+-- >>> showHex (h 16) ""
+-- "80008000"
+-- >>> showHex (h 32) ""
+-- "80000000"
+h :: Int -> Word32
+h 2  = 0xaaaaaaaa
+h 4  = 0x88888888
+h 8  = 0x80808080
+h 16 = 0x80008000
+h 32 = 0x80000000
+h k  = error ("Invalid h k where k = " ++ show k)
+{-# INLINE h #-}
+
+-- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8, 16, 32 }.
+--
+-- The subtraction respects 2's complement so sub-words may be regarded as signed or unsigned words.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (kBitDiff 8 0x04030201 0x02020101) ""
+-- "2010100"
+-- >>> showHex (kBitDiff 8 0x04030201 0x01020304) ""
+-- "301fffd"
+-- >>> showHex (kBitDiff 8 0x200000ff 0x100000ff) ""
+-- "10000000"
+kBitDiff :: Int -> Word32 -> Word32 -> Word32
+kBitDiff k x y = ((x .|. h k) - (y .&. comp (h k))) .^. ((x .^. comp y) .&. h k)
+{-# INLINE kBitDiff #-}
+
+-- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8, 16, 32 } where results are bounded from below by 0.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (kBitDiffPos 8 0x04030201 0x02020101) ""
+-- "2010100"
+-- >>> showHex (kBitDiffPos 8 0x04030201 0x01020304) ""
+-- "3010000"
+-- >>> showHex (kBitDiffPos 8 0x200000ff 0x100000ff) "" -- produces nonsense in the last sub-word
+-- "10000000"
+kBitDiffPos :: Int -> Word32 -> Word32 -> Word32
+kBitDiffPos k x y = let d = kBitDiff k x y in d .&. kBitDiff k 0 ((comp d .&. h 8) .>. fromIntegral (k - 1))
+{-# INLINE kBitDiffPos #-}
+
+-- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8, 16, 32 } where all the sub-words of 'x' and 'y' must
+-- not have the signed bit set for the result to be meaningful.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (kBitDiffUnsafe 8 0x04030201 0x02020101) ""
+-- "2010100"
+-- >>> showHex (kBitDiffUnsafe 8 0x04030201 0x05060708) ""
+-- "fffdfbf9"
+-- >>> showHex (kBitDiffUnsafe 8 0x200000ff 0x100000ff) ""
+-- "10000080"
+kBitDiffUnsafe :: Int -> Word32 -> Word32 -> Word32
+kBitDiffUnsafe k x y = ((x .|. h k) - y) .^. h k
+{-# INLINE kBitDiffUnsafe #-}
diff --git a/src/HaskellWorks/Data/Bits/Broadword/Word64.hs b/src/HaskellWorks/Data/Bits/Broadword/Word64.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Bits/Broadword/Word64.hs
@@ -0,0 +1,107 @@
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+module HaskellWorks.Data.Bits.Broadword.Word64
+  ( h
+  , l
+  , kBitDiff
+  , kBitDiffPos
+  , kBitDiffUnsafe
+  ) where
+
+import Data.Word
+import HaskellWorks.Data.Bits.BitWise
+
+-- | Initialise all sub-words of size k where 'k' ∈ { 2, 4, 8, 16, 32, 64 } such that the lowest bit is set to 1 and all other bits are cleared.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (l 2) ""
+-- "5555555555555555"
+-- >>> showHex (l 4) ""
+-- "1111111111111111"
+-- >>> showHex (l 8) ""
+-- "101010101010101"
+-- >>> showHex (l 16) ""
+-- "1000100010001"
+-- >>> showHex (l 32) ""
+-- "100000001"
+-- >>> showHex (l 64) ""
+-- "1"
+l :: Int -> Word64
+l 2  = 0x5555555555555555
+l 4  = 0x1111111111111111
+l 8  = 0x0101010101010101
+l 16 = 0x0001000100010001
+l 32 = 0x0000000100000001
+l 64 = 0x0000000000000001
+l k  = error ("Invalid h k where k = " ++ show k)
+{-# INLINE l #-}
+
+-- | Initialise all sub-words of size k where 'k' ∈ { 2, 4, 8, 16, 32, 64 } such that the highest bit is set to 1 and all other bits are cleared.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (h 2) ""
+-- "aaaaaaaaaaaaaaaa"
+-- >>> showHex (h 4) ""
+-- "8888888888888888"
+-- >>> showHex (h 8) ""
+-- "8080808080808080"
+-- >>> showHex (h 16) ""
+-- "8000800080008000"
+-- >>> showHex (h 32) ""
+-- "8000000080000000"
+-- >>> showHex (h 64) ""
+-- "8000000000000000"
+h :: Int -> Word64
+h 2  = 0xaaaaaaaaaaaaaaaa
+h 4  = 0x8888888888888888
+h 8  = 0x8080808080808080
+h 16 = 0x8000800080008000
+h 32 = 0x8000000080000000
+h 64 = 0x8000000000000000
+h k  = error ("Invalid h k where k = " ++ show k)
+{-# INLINE h #-}
+
+-- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8, 16, 32, 64 }.
+--
+-- The subtraction respects 2's complement so sub-words may be regarded as signed or unsigned words.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (kBitDiff 8 0x0807060504030201 0x0404030302020101) ""
+-- "403030202010100"
+-- >>> showHex (kBitDiff 8 0x0807060504030201 0x0102030405060708) ""
+-- "7050301fffdfbf9"
+-- >>> showHex (kBitDiff 8 0x20000000000000ff 0x10000000000000ff) ""
+-- "1000000000000000"
+kBitDiff :: Int -> Word64 -> Word64 -> Word64
+kBitDiff k x y = ((x .|. h k) - (y .&. comp (h k))) .^. ((x .^. comp y) .&. h k)
+{-# INLINE kBitDiff #-}
+
+-- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8, 16, 32, 64 } where results are bounded from below by 0.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (kBitDiffPos 8 0x0807060504030201 0x0404030302020101) ""
+-- "403030202010100"
+-- >>> showHex (kBitDiffPos 8 0x0807060504030201 0x0102030405060708) ""
+-- "705030100000000"
+-- >>> showHex (kBitDiffPos 8 0x20000000000000ff 0x10000000000000ff) ""
+-- "1000000000000000"
+kBitDiffPos :: Int -> Word64 -> Word64 -> Word64
+kBitDiffPos k x y = let d = kBitDiff k x y in d .&. kBitDiff k 0 ((comp d .&. h 8) .>. fromIntegral (k - 1))
+{-# INLINE kBitDiffPos #-}
+
+-- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8, 16, 32, 64 } where all the sub-words of 'x' and 'y' must
+-- not have the signed bit set for the result to be meaningful.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (kBitDiffUnsafe 8 0x0807060504030201 0x0404030302020101) ""
+-- "403030202010100"
+-- >>> showHex (kBitDiffUnsafe 8 0x0807060504030201 0x0102030405060708) ""
+-- "7050301fffdfbf9"
+-- >>> showHex (kBitDiffUnsafe 8 0x20000000000000ff 0x10000000000000ff) "" -- produces nonsense in the last sub-word
+-- "1000000000000080"
+kBitDiffUnsafe :: Int -> Word64 -> Word64 -> Word64
+kBitDiffUnsafe k x y = ((x .|. h k) - y) .^. h k
+{-# INLINE kBitDiffUnsafe #-}
diff --git a/src/HaskellWorks/Data/Bits/Broadword/Word8.hs b/src/HaskellWorks/Data/Bits/Broadword/Word8.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Bits/Broadword/Word8.hs
@@ -0,0 +1,89 @@
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+module HaskellWorks.Data.Bits.Broadword.Word8
+  ( h
+  , l
+  , kBitDiff
+  , kBitDiffPos
+  , kBitDiffUnsafe
+  ) where
+
+import Data.Word
+import HaskellWorks.Data.Bits.BitWise
+
+-- | Initialise all sub-words of size k where 'k' ∈ { 2, 4, 8, 16, 32 } such that the lowest bit is set to 1 and all other bits are cleared.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (l 2) ""
+-- "55"
+-- >>> showHex (l 4) ""
+-- "11"
+-- >>> showHex (l 8) ""
+-- "1"
+l :: Int -> Word8
+l 2 = 0x55
+l 4 = 0x11
+l 8 = 0x01
+l k = error ("Invalid h k where k = " ++ show k)
+{-# INLINE l #-}
+
+-- | Initialise all sub-words of size k where 'k' ∈ { 2, 4, 8, 16, 32 } such that the highest bit is set to 1 and all other bits are cleared.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (h 2) ""
+-- "aa"
+-- >>> showHex (h 4) ""
+-- "88"
+-- >>> showHex (h 8) ""
+-- "80"
+h :: Int -> Word8
+h 2 = 0xaa
+h 4 = 0x88
+h 8 = 0x80
+h k = error ("Invalid h k where k = " ++ show k)
+{-# INLINE h #-}
+
+-- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8 }.
+--
+-- The subtraction respects 2's complement so sub-words may be regarded as signed or unsigned words.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (kBitDiff 8 0x02 0x01) ""
+-- "1"
+-- >>> showHex (kBitDiff 8 0x01 0x02) ""
+-- "ff"
+-- >>> showHex (kBitDiff 8 0xff 0xff) ""
+-- "0"
+kBitDiff :: Int -> Word8 -> Word8 -> Word8
+kBitDiff k x y = ((x .|. h k) - (y .&. comp (h k))) .^. ((x .^. comp y) .&. h k)
+{-# INLINE kBitDiff #-}
+
+-- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8 } where results are bounded from below by 0.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (kBitDiff 8 0x02 0x01) ""
+-- "1"
+-- >>> showHex (kBitDiff 8 0x01 0x02) ""
+-- "ff"
+-- >>> showHex (kBitDiff 8 0xff 0xff) ""
+-- "0"
+kBitDiffPos :: Int -> Word8 -> Word8 -> Word8
+kBitDiffPos k x y = let d = kBitDiff k x y in d .&. kBitDiff k 0 ((comp d .&. h 8) .>. fromIntegral (k - 1))
+{-# INLINE kBitDiffPos #-}
+
+-- | Broadword subtraction of sub-words of size 'k' where 'k' ∈ { 2, 4, 8 } where all the sub-words of 'x' and 'y' must
+-- not have the signed bit set for the result to be meaningful.
+--
+-- >>> import Numeric(showHex)
+-- >>> showHex (kBitDiffUnsafe 8 0x02 0x01) ""
+-- "1"
+-- >>> showHex (kBitDiffUnsafe 8 0x01 0x02) ""
+-- "ff"
+-- >>> showHex (kBitDiffUnsafe 8 0xff 0xff) "" -- produces nonsense in the last sub-word
+-- "80"
+kBitDiffUnsafe :: Int -> Word8 -> Word8 -> Word8
+kBitDiffUnsafe k x y = ((x .|. h k) - y) .^. h k
+{-# INLINE kBitDiffUnsafe #-}
diff --git a/src/HaskellWorks/Data/Bits/Word64.hs b/src/HaskellWorks/Data/Bits/Word64.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Bits/Word64.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+module HaskellWorks.Data.Bits.Word64
+  ( lsb
+  ) where
+
+import Data.Word
+import HaskellWorks.Data.Bits.BitWise
+
+import qualified Data.Bits as DB
+
+-- | Returns the position of the least significant bit (0-based).
+--
+-- This is equivalent to 'DB.countTrailingZeros' except for when there are no bits set.  In which case
+-- return a word with all bits set.
+--
+-- >>> lsb 8
+-- 3
+-- >>> lsb 1
+-- 0
+-- >>> lsb 0
+-- 18446744073709551615
+lsb :: Word64 -> Word64
+lsb w = let r = fromIntegral (DB.countTrailingZeros w) in r .|. negate ((r .>. 6) .&. 0x1)
+{-# INLINE lsb #-}
