1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE MagicHash #-}
3-- |
4-- Module      : Data.Unicode.Internal.Bits
5-- Copyright   : (c) 2020 Andrew Lelechenko
6--               (c) 2020 Composewell Technologies
7--
8-- License     : BSD-3-Clause
9-- Maintainer  : harendra.kumar@gmail.com
10-- Stability   : experimental
11-- Portability : GHC
12--
13-- Fast, static bitmap lookup utilities
14
15module Data.Unicode.Internal.Bits
16    (
17      lookupBit64
18    ) where
19
20import Data.Bits (finiteBitSize, popCount)
21import GHC.Exts
22       (Addr#, Int(..), Word(..), indexWordOffAddr#, and#, andI#,
23        uncheckedIShiftRL#, uncheckedShiftL#)
24
25-- | @lookup64 addr index@ looks up the bit stored at bit index @index@ using a
26-- bitmap starting at the address @addr@. Looks up the 64-bit word containing
27-- the bit and then the bit in that word. The caller must make sure that the
28-- 64-bit word at the byte address (addr + index / 64) * 8 is legally
29-- accessible memory.
30--
31lookupBit64 :: Addr# -> Int -> Bool
32lookupBit64 addr# (I# index#) = W# (word## `and#` bitMask##) /= 0
33  where
34    !fbs@(I# fbs#) = finiteBitSize (0 :: Word) - 1
35    !(I# logFbs#) = case fbs of
36      31 -> 5
37      63 -> 6
38      _  -> popCount fbs -- this is a really weird architecture
39
40    wordIndex# = index# `uncheckedIShiftRL#` logFbs#
41    word## = indexWordOffAddr# addr# wordIndex#
42    bitIndex# = index# `andI#` fbs#
43    bitMask## = 1## `uncheckedShiftL#` bitIndex#
44