module Data.CompactMap.Generic ( CompactMap , fromList , toVector , lookup , getLE , getIndex ) where import qualified Data.Vector.Generic as V import GHC.Exts (sortWith) import Control.Applicative import Prelude hiding (lookup) data CompactMap vec k v = CompactMap { getMap :: vec v , _gkf :: v -> k } instance (V.Vector vec v, Show v) => Show (CompactMap vec k v) where show = show . V.toList . getMap fromList :: (V.Vector vec v, Ord k) => [v] -> (v -> k) -> CompactMap vec k v fromList lst f = CompactMap (V.fromList $ sortWith f lst) f toVector :: V.Vector vec v => CompactMap vec k v -> vec v toVector (CompactMap v _) = v lookup :: (V.Vector vec v, Ord k) => k -> CompactMap vec k v -> Maybe v lookup k cm@(CompactMap _ f) = getLE k cm >>= \(_,r) -> if f r == k then Just r else Nothing getLE :: (V.Vector vec v, Ord k) => k -> CompactMap vec k v -> Maybe (Int, v) getLE k (CompactMap lst f) = go 0 (sz - 1) where sz = V.length lst go l h | m < l = Nothing | m > h = Nothing | k' == k = Just (m, x) | l >= h = checkLower <|> Just (m, x) | k < k' = checkLower <|> go l (m - 1) | otherwise = go (m + 1) h where checkLower | m < 1 = Nothing | k > k_1 = Just (m - 1, x_1) | otherwise = Nothing m = (l + h) `div` 2 x = lst V.! m k' = f x x_1 = lst V.! (m - 1) k_1 = f x_1 getIndex :: V.Vector vec v => Int -> CompactMap vec k v -> Maybe v getIndex i (CompactMap lst _) = lst V.!? i