diff options
Diffstat (limited to 'src/Data/Word64Map.hs')
-rw-r--r-- | src/Data/Word64Map.hs | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/Data/Word64Map.hs b/src/Data/Word64Map.hs new file mode 100644 index 00000000..9e93c8c8 --- /dev/null +++ b/src/Data/Word64Map.hs | |||
@@ -0,0 +1,62 @@ | |||
1 | {-# LANGUAGE RankNTypes #-} | ||
2 | {-# LANGUAGE ScopedTypeVariables #-} | ||
3 | {-# LANGUAGE UnboxedTuples #-} | ||
4 | module Data.Word64Map where | ||
5 | |||
6 | import Data.Bits | ||
7 | import qualified Data.IntMap as IntMap | ||
8 | ;import Data.IntMap (IntMap) | ||
9 | import Data.Typeable | ||
10 | import Data.Word | ||
11 | |||
12 | -- | Since 'Int' may be 32 or 64 bits, this function is provided as a | ||
13 | -- convenience to test if an integral type, such as 'Data.Word.Word64', can be | ||
14 | -- safely transformed into an 'Int' for use with 'IntMap'. | ||
15 | -- | ||
16 | -- Returns 'True' if the proxied type can be losslessly converted to 'Int' using | ||
17 | -- 'fromIntegral'. | ||
18 | fitsInInt :: forall proxy word. (Bounded word, Integral word) => proxy word -> Bool | ||
19 | fitsInInt proxy = (original == casted) | ||
20 | where | ||
21 | original = div maxBound 2 :: word | ||
22 | casted = fromIntegral (fromIntegral original :: Int) :: word | ||
23 | |||
24 | newtype Word64Map a = Word64Map (IntMap (IntMap a)) | ||
25 | |||
26 | empty :: Word64Map a | ||
27 | empty = Word64Map IntMap.empty | ||
28 | |||
29 | -- Warning: This function assumes an 'Int' is either 64 or 32 bits. | ||
30 | keyFrom64 :: Word64 -> (# Int,Int #) | ||
31 | keyFrom64 w8 = | ||
32 | if fitsInInt (Proxy :: Proxy Word64) | ||
33 | then (# fromIntegral w8 , 0 #) | ||
34 | else (# fromIntegral (w8 `shiftR` 32), fromIntegral w8 #) | ||
35 | {-# INLINE keyFrom64 #-} | ||
36 | |||
37 | lookup :: Word64 -> Word64Map b -> Maybe b | ||
38 | lookup w8 (Word64Map m) | (# hi,lo #) <- keyFrom64 w8 = do | ||
39 | m' <- IntMap.lookup hi m | ||
40 | IntMap.lookup lo m' | ||
41 | {-# INLINE lookup #-} | ||
42 | |||
43 | insert :: Word64 -> b -> Word64Map b -> Word64Map b | ||
44 | insert w8 b (Word64Map m) | (# hi,lo #) <- keyFrom64 w8 | ||
45 | = Word64Map $ IntMap.alter (Just . maybe (IntMap.singleton lo b) | ||
46 | (IntMap.insert lo b)) | ||
47 | hi | ||
48 | m | ||
49 | {-# INLINE insert #-} | ||
50 | |||
51 | delete :: Word64 -> Word64Map b -> Word64Map b | ||
52 | delete w8 (Word64Map m) | (# hi,lo #) <- keyFrom64 w8 | ||
53 | = Word64Map $ IntMap.alter (maybe Nothing | ||
54 | (\m' -> case IntMap.delete lo m' of | ||
55 | m'' | IntMap.null m'' -> Nothing | ||
56 | m'' -> Just m'')) | ||
57 | hi | ||
58 | m | ||
59 | {-# INLINE delete #-} | ||
60 | |||
61 | |||
62 | |||