{-# 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 :: Word64 -> Word64
lsb Word64
w = let r :: Word64
r = Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int
forall b. FiniteBits b => b -> Int
DB.countTrailingZeros Word64
w) in Word64
r Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.|. Word64 -> Word64
forall a. Num a => a -> a
negate ((Word64
r Word64 -> Word64 -> Word64
forall a. Shift a => a -> Word64 -> a
.>. Word64
6) Word64 -> Word64 -> Word64
forall a. BitWise a => a -> a -> a
.&. Word64
0x1)
{-# INLINE lsb #-}