@@ -39,6 +39,8 @@ import Data.IntMap.Strict (IntMap)
39import Data.Kind (Type)
39import Data.Kind (Type)
40import Data.List (nubBy)
40import Data.List (nubBy)
41import Data.Maybe (fromJust)
41import Data.Maybe (fromJust)
42+import Data.Primitive.Array (Array, indexArray, mapArray')
43+import Data.Primitive.PrimArray (PrimArray, indexPrimArray, sizeofPrimArray)
42import Data.Proxy (Proxy (..))
44import Data.Proxy (Proxy (..))
43import Data.Typeable (Typeable, typeRep, typeRepFingerprint)
45import Data.Typeable (Typeable, typeRep, typeRepFingerprint)
44import GHC.Base (Any, Int (..), Int#, (*#), (+#), (<#))
46import GHC.Base (Any, Int (..), Int#, (*#), (+#), (<#))
@@ -49,14 +51,13 @@ import GHC.Word (Word64 (..))
49import Unsafe.Coerce (unsafeCoerce)
51import Unsafe.Coerce (unsafeCoerce)
51import qualified Data.IntMap.Strict as IM
53import qualified Data.IntMap.Strict as IM
52−import qualified Data.Vector as V
54+import qualified GHC.Exts as GHC (fromList, toList)
53−import qualified Data.Vector.Unboxed as Unboxed
55-- | Map-like data structure that keeps types as keys.
56-- | Map-like data structure that keeps types as keys.
56data TypeRepMap (f :: k -> Type) = TypeRepMap
57data TypeRepMap (f :: k -> Type) = TypeRepMap
57− { fingerprintAs :: {-# UNPACK #-} !(Unboxed.Vector Word64)
58+ { fingerprintAs :: {-# UNPACK #-} !(PrimArray Word64)
58− , fingerprintBs :: {-# UNPACK #-} !(Unboxed.Vector Word64)
59+ , fingerprintBs :: {-# UNPACK #-} !(PrimArray Word64)
59− , anys :: {-# UNPACK #-} !(V.Vector Any)
60+ , anys :: {-# UNPACK #-} !(Array Any)
62-- | Shows only 'Fingerprint's.
63-- | Shows only 'Fingerprint's.
@@ -66,8 +67,8 @@ instance Show (TypeRepMap f) where
66-- | Returns the list of 'Fingerprint's from 'TypeRepMap'.
67-- | Returns the list of 'Fingerprint's from 'TypeRepMap'.
67toFps :: TypeRepMap f -> [Fingerprint]
68toFps :: TypeRepMap f -> [Fingerprint]
68toFps TypeRepMap{..} = zipWith Fingerprint
69toFps TypeRepMap{..} = zipWith Fingerprint
69− (Unboxed.toList fingerprintAs)
70+ (GHC.toList fingerprintAs)
70− (Unboxed.toList fingerprintBs)
71+ (GHC.toList fingerprintBs)
73-- | Empty structure.
74-- | Empty structure.
@@ -121,7 +122,7 @@ Just [True]
123hoist :: (forall x. f x -> g x) -> TypeRepMap f -> TypeRepMap g
124hoist :: (forall x. f x -> g x) -> TypeRepMap f -> TypeRepMap g
124−hoist f (TypeRepMap as bs ans) = TypeRepMap as bs $ V.map (toAny . f . fromAny) ans
125+hoist f (TypeRepMap as bs ans) = TypeRepMap as bs $ mapArray' (toAny . f . fromAny) ans
126{- | Returns 'True' if there exist value of given type.
127{- | Returns 'True' if there exist value of given type.
@@ -145,7 +146,7 @@ Just (Identity 11)
147lookup :: forall a f . Typeable a => TypeRepMap f -> Maybe (f a)
148lookup :: forall a f . Typeable a => TypeRepMap f -> Maybe (f a)
148−lookup tVect = fromAny . (anys tVect V.!)
149+lookup tVect = fromAny . (anys tVect `indexArray`)
149 <$> cachedBinarySearch (typeFp @a)
150 <$> cachedBinarySearch (typeFp @a)
150 (fingerprintAs tVect)
151 (fingerprintAs tVect)
151 (fingerprintBs tVect)
152 (fingerprintBs tVect)
@@ -153,22 +154,22 @@ lookup tVect = fromAny . (anys tVect V.!)
154-- | Returns the size of the 'TypeRepMap'.
155-- | Returns the size of the 'TypeRepMap'.
155size :: TypeRepMap f -> Int
156size :: TypeRepMap f -> Int
156−size = Unboxed.length . fingerprintAs
157+size = sizeofPrimArray . fingerprintAs
157{-# INLINE size #-}
158{-# INLINE size #-}
159-- | Binary searched based on this article
160-- | Binary searched based on this article
160-- http://bannalia.blogspot.com/2015/06/cache-friendly-binary-search.html
161-- http://bannalia.blogspot.com/2015/06/cache-friendly-binary-search.html
161-- with modification for our two-vector search case.
162-- with modification for our two-vector search case.
162−cachedBinarySearch :: Fingerprint -> Unboxed.Vector Word64 -> Unboxed.Vector Word64 -> Maybe Int
163+cachedBinarySearch :: Fingerprint -> PrimArray Word64 -> PrimArray Word64 -> Maybe Int
163cachedBinarySearch (Fingerprint (W64# a) (W64# b)) fpAs fpBs = inline (go 0#)
164cachedBinarySearch (Fingerprint (W64# a) (W64# b)) fpAs fpBs = inline (go 0#)
165 go :: Int# -> Maybe Int
166 go :: Int# -> Maybe Int
166 go i = case i <# len of
167 go i = case i <# len of
167 0# -> Nothing
168 0# -> Nothing
168− _ -> let !(W64# valA) = Unboxed.unsafeIndex fpAs (I# i) in case a `ltWord#` valA of
169+ _ -> let !(W64# valA) = indexPrimArray fpAs (I# i) in case a `ltWord#` valA of
169 0# -> case a `eqWord#` valA of
170 0# -> case a `eqWord#` valA of
170 0# -> go (2# *# i +# 2#)
171 0# -> go (2# *# i +# 2#)
171− _ -> let !(W64# valB) = Unboxed.unsafeIndex fpBs (I# i) in case b `eqWord#` valB of
172+ _ -> let !(W64# valB) = indexPrimArray fpBs (I# i) in case b `eqWord#` valB of
172 0# -> case b `ltWord#` valB of
173 0# -> case b `ltWord#` valB of
173 0# -> go (2# *# i +# 2#)
174 0# -> go (2# *# i +# 2#)
174 _ -> go (2# *# i +# 1#)
175 _ -> go (2# *# i +# 1#)
@@ -176,7 +177,7 @@ cachedBinarySearch (Fingerprint (W64# a) (W64# b)) fpAs fpBs = inline (go 0#)
176 _ -> go (2# *# i +# 1#)
177 _ -> go (2# *# i +# 1#)
178 len :: Int#
179 len :: Int#
179− len = let !(I# l) = Unboxed.length fpAs in l
180+ len = let !(I# l) = sizeofPrimArray fpAs in l
180{-# INLINE cachedBinarySearch #-}
181{-# INLINE cachedBinarySearch #-}
182----------------------------------------------------------------------------
183----------------------------------------------------------------------------
@@ -194,7 +195,7 @@ typeFp = typeRepFingerprint $ typeRep $ Proxy @a
194{-# INLINE typeFp #-}
195{-# INLINE typeFp #-}
196toPairList :: TypeRepMap f -> [(Fingerprint, Any)]
197toPairList :: TypeRepMap f -> [(Fingerprint, Any)]
197−toPairList trMap = zip (toFps trMap) (V.toList $ anys trMap)
198+toPairList trMap = zip (toFps trMap) (GHC.toList $ anys trMap)
199deleteByFst :: Eq a => a -> [(a, b)] -> [(a, b)]
200deleteByFst :: Eq a => a -> [(a, b)] -> [(a, b)]
200deleteByFst x = filter ((/= x) . fst)
201deleteByFst x = filter ((/= x) . fst)
@@ -236,7 +237,7 @@ calcFp :: Typeable a => f a -> Fingerprint
236calcFp = typeRepFingerprint . typeRep . fromF
237calcFp = typeRepFingerprint . typeRep . fromF
238fromListPairs :: [(Fingerprint, Any)] -> TypeRepMap f
239fromListPairs :: [(Fingerprint, Any)] -> TypeRepMap f
239−fromListPairs kvs = TypeRepMap (Unboxed.fromList fpAs) (Unboxed.fromList fpBs) (V.fromList ans)
240+fromListPairs kvs = TypeRepMap (GHC.fromList fpAs) (GHC.fromList fpBs) (GHC.fromList ans)
241 (fpAs, fpBs) = unzip $ map (\(Fingerprint a b) -> (a, b)) fps
242 (fpAs, fpBs) = unzip $ map (\(Fingerprint a b) -> (a, b)) fps
242 (fps, ans) = unzip $ fromSortedList $ sortWith fst $ nubByFst kvs
243 (fps, ans) = unzip $ fromSortedList $ sortWith fst $ nubByFst kvs