2 % (c) The AQUA Project, Glasgow University, 1994-1996
4 \section[UniqFM]{Specialised finite maps, for things with @Uniques@}
6 Based on @FiniteMaps@ (as you would expect).
8 Basically, the things need to be in class @Uniquable@, and we use the
9 @uniqueOf@ method to grab their @Uniques@.
11 (A similar thing to @UniqSet@, as opposed to @Set@.)
15 UniqFM, -- abstract type
23 addListToUFM,addListToUFM_C,
25 addListToUFM_Directly,
40 lookupUFM, lookupUFM_Directly,
41 lookupWithDefaultUFM, lookupWithDefaultUFM_Directly,
47 #include "HsVersions.h"
49 import {-# SOURCE #-} Name ( Name )
51 import Unique ( Uniquable(..), Unique, u2i, mkUniqueGrimily )
53 import GlaExts -- Lots of Int# operations
55 #if ! OMIT_NATIVE_CODEGEN
58 #define IF_NCG(a) {--}
62 %************************************************************************
64 \subsection{The @UniqFM@ type, and signatures for the functions}
66 %************************************************************************
68 We use @FiniteMaps@, with a (@uniqueOf@-able) @Unique@ as ``key''.
71 emptyUFM :: UniqFM elt
72 isNullUFM :: UniqFM elt -> Bool
73 unitUFM :: Uniquable key => key -> elt -> UniqFM elt
74 unitDirectlyUFM -- got the Unique already
75 :: Unique -> elt -> UniqFM elt
76 listToUFM :: Uniquable key => [(key,elt)] -> UniqFM elt
78 :: [(Unique, elt)] -> UniqFM elt
80 addToUFM :: Uniquable key => UniqFM elt -> key -> elt -> UniqFM elt
81 addListToUFM :: Uniquable key => UniqFM elt -> [(key,elt)] -> UniqFM elt
83 :: UniqFM elt -> Unique -> elt -> UniqFM elt
85 addToUFM_C :: Uniquable key => (elt -> elt -> elt)
86 -> UniqFM elt -> key -> elt -> UniqFM elt
87 addListToUFM_C :: Uniquable key => (elt -> elt -> elt)
88 -> UniqFM elt -> [(key,elt)]
91 delFromUFM :: Uniquable key => UniqFM elt -> key -> UniqFM elt
92 delListFromUFM :: Uniquable key => UniqFM elt -> [key] -> UniqFM elt
93 delFromUFM_Directly :: UniqFM elt -> Unique -> UniqFM elt
95 plusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
97 plusUFM_C :: (elt -> elt -> elt)
98 -> UniqFM elt -> UniqFM elt -> UniqFM elt
100 minusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
102 intersectUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
103 intersectUFM_C :: (elt -> elt -> elt)
104 -> UniqFM elt -> UniqFM elt -> UniqFM elt
105 foldUFM :: (elt -> a -> a) -> a -> UniqFM elt -> a
106 mapUFM :: (elt1 -> elt2) -> UniqFM elt1 -> UniqFM elt2
107 filterUFM :: (elt -> Bool) -> UniqFM elt -> UniqFM elt
109 sizeUFM :: UniqFM elt -> Int
110 elemUFM :: Uniquable key => key -> UniqFM elt -> Bool
112 lookupUFM :: Uniquable key => UniqFM elt -> key -> Maybe elt
113 lookupUFM_Directly -- when you've got the Unique already
114 :: UniqFM elt -> Unique -> Maybe elt
116 :: Uniquable key => UniqFM elt -> elt -> key -> elt
117 lookupWithDefaultUFM_Directly
118 :: UniqFM elt -> elt -> Unique -> elt
120 keysUFM :: UniqFM elt -> [Int] -- Get the keys
121 eltsUFM :: UniqFM elt -> [elt]
122 ufmToList :: UniqFM elt -> [(Unique, elt)]
125 %************************************************************************
127 \subsection{The @IdFinMap@ and @TyVarFinMap@ specialisations for Ids/TyVars}
129 %************************************************************************
132 -- Turn off for now, these need to be updated (SDM 4/98)
134 {- #ifdef __GLASGOW_HASKELL__ -}
135 -- I don't think HBC was too happy about this (WDP 94/10)
138 addListToUFM :: UniqFM elt -> [(Name, elt)] -> UniqFM elt
141 addListToUFM_C :: (elt -> elt -> elt) -> UniqFM elt -> [(Name, elt)] -> UniqFM elt
144 addToUFM :: UniqFM elt -> Unique -> elt -> UniqFM elt
147 listToUFM :: [(Unique, elt)] -> UniqFM elt
150 lookupUFM :: UniqFM elt -> Name -> Maybe elt
151 , UniqFM elt -> Unique -> Maybe elt
154 {- #endif {- __GLASGOW_HASKELL__ -} -}
157 %************************************************************************
159 \subsection{Andy Gill's underlying @UniqFM@ machinery}
161 %************************************************************************
163 ``Uniq Finite maps'' are the heart and soul of the compiler's
164 lookup-tables/environments. Important stuff! It works well with
165 Dense and Sparse ranges.
166 Both @Uq@ Finite maps and @Hash@ Finite Maps
167 are built ontop of Int Finite Maps.
169 This code is explained in the paper:
171 A Gill, S Peyton Jones, B O'Sullivan, W Partain and Aqua Friends
172 "A Cheap balancing act that grows on a tree"
173 Glasgow FP Workshop, Sep 1994, pp??-??
176 %************************************************************************
178 \subsubsection{The @UniqFM@ type, and signatures for the functions}
180 %************************************************************************
182 @UniqFM a@ is a mapping from Unique to a.
184 First, the DataType itself; which is either a Node, a Leaf, or an Empty.
189 | LeafUFM FAST_INT ele
190 | NodeUFM FAST_INT -- the switching
191 FAST_INT -- the delta
195 -- for debugging only :-)
197 instance Text (UniqFM a) where
198 showsPrec _ (NodeUFM a b t1 t2) =
199 showString "NodeUFM " . shows (IBOX(a))
200 . showString " " . shows (IBOX(b))
201 . showString " (" . shows t1
202 . showString ") (" . shows t2
204 showsPrec _ (LeafUFM x a) = showString "LeafUFM " . shows (IBOX(x))
205 showsPrec _ (EmptyUFM) = id
209 %************************************************************************
211 \subsubsection{The @UniqFM@ functions}
213 %************************************************************************
215 First the ways of building a UniqFM.
219 unitUFM key elt = mkLeafUFM (u2i (uniqueOf key)) elt
220 unitDirectlyUFM key elt = mkLeafUFM (u2i key) elt
222 listToUFM key_elt_pairs
223 = addListToUFM_C use_snd EmptyUFM key_elt_pairs
225 listToUFM_Directly uniq_elt_pairs
226 = addListToUFM_directly_C use_snd EmptyUFM uniq_elt_pairs
229 Now ways of adding things to UniqFMs.
231 There is an alternative version of @addListToUFM_C@, that uses @plusUFM@,
232 but the semantics of this operation demands a linear insertion;
233 perhaps the version without the combinator function
234 could be optimised using it.
237 addToUFM fm key elt = addToUFM_C use_snd fm key elt
239 addToUFM_Directly fm u elt = insert_ele use_snd fm (u2i u) elt
241 addToUFM_C combiner fm key elt
242 = insert_ele combiner fm (u2i (uniqueOf key)) elt
244 addListToUFM fm key_elt_pairs = addListToUFM_C use_snd fm key_elt_pairs
245 addListToUFM_Directly fm uniq_elt_pairs = addListToUFM_directly_C use_snd fm uniq_elt_pairs
247 addListToUFM_C combiner fm key_elt_pairs
248 = foldl (\ fm (k, e) -> insert_ele combiner fm (u2i (uniqueOf k)) e)
251 addListToUFM_directly_C combiner fm uniq_elt_pairs
252 = foldl (\ fm (k, e) -> insert_ele combiner fm (u2i k) e)
256 Now ways of removing things from UniqFM.
259 delListFromUFM fm lst = foldl delFromUFM fm lst
261 delFromUFM fm key = delete fm (u2i (uniqueOf key))
262 delFromUFM_Directly fm u = delete fm (u2i u)
264 delete EmptyUFM _ = EmptyUFM
265 delete fm key = del_ele fm
267 del_ele :: UniqFM a -> UniqFM a
269 del_ele lf@(LeafUFM j _)
270 | j _EQ_ key = EmptyUFM
271 | otherwise = lf -- no delete!
273 del_ele nd@(NodeUFM j p t1 t2)
275 = mkSLNodeUFM (NodeUFMData j p) (del_ele t1) t2
277 = mkLSNodeUFM (NodeUFMData j p) t1 (del_ele t2)
279 del_ele _ = panic "Found EmptyUFM FM when rec-deleting"
282 Now ways of adding two UniqFM's together.
285 plusUFM tr1 tr2 = plusUFM_C use_snd tr1 tr2
287 plusUFM_C f EmptyUFM tr = tr
288 plusUFM_C f tr EmptyUFM = tr
289 plusUFM_C f fm1 fm2 = mix_trees fm1 fm2
291 mix_trees (LeafUFM i a) t2 = insert_ele (flip f) t2 i a
292 mix_trees t1 (LeafUFM i a) = insert_ele f t1 i a
294 mix_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
296 (ask_about_common_ancestor
300 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
304 -- t1 t2 t1' t2' j j'
309 mix_branches (NewRoot nd False)
310 = mkLLNodeUFM nd left_t right_t
311 mix_branches (NewRoot nd True)
312 = mkLLNodeUFM nd right_t left_t
318 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
320 mix_branches (SameRoot)
321 = mkSSNodeUFM (NodeUFMData j p)
324 -- Now the 4 different other ways; all like this:
326 -- Given j >^ j' (and, say, j > j')
330 -- t1 t2 t1' t2' t1 t2 + j'
333 mix_branches (LeftRoot Leftt) -- | trace "LL" True
336 (mix_trees t1 right_t)
339 mix_branches (LeftRoot Rightt) -- | trace "LR" True
343 (mix_trees t2 right_t)
345 mix_branches (RightRoot Leftt) -- | trace "RL" True
348 (mix_trees left_t t1')
351 mix_branches (RightRoot Rightt) -- | trace "RR" True
355 (mix_trees left_t t2')
357 mix_trees _ _ = panic "EmptyUFM found when inserting into plusInt"
360 And ways of subtracting them. First the base cases,
361 then the full D&C approach.
364 minusUFM EmptyUFM _ = EmptyUFM
365 minusUFM t1 EmptyUFM = t1
366 minusUFM fm1 fm2 = minus_trees fm1 fm2
369 -- Notice the asymetry of subtraction
371 minus_trees lf@(LeafUFM i a) t2 =
376 minus_trees t1 (LeafUFM i _) = delete t1 i
378 minus_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
380 (ask_about_common_ancestor
384 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
388 -- t1 t2 t1' t2' t1 t2
393 minus_branches (NewRoot nd _) = left_t
399 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
401 minus_branches (SameRoot)
402 = mkSSNodeUFM (NodeUFMData j p)
405 -- Now the 4 different other ways; all like this:
406 -- again, with asymatry
409 -- The left is above the right
411 minus_branches (LeftRoot Leftt)
414 (minus_trees t1 right_t)
416 minus_branches (LeftRoot Rightt)
420 (minus_trees t2 right_t)
423 -- The right is above the left
425 minus_branches (RightRoot Leftt)
426 = minus_trees left_t t1'
427 minus_branches (RightRoot Rightt)
428 = minus_trees left_t t2'
430 minus_trees _ _ = panic "EmptyUFM found when insering into plusInt"
433 And taking the intersection of two UniqFM's.
436 intersectUFM t1 t2 = intersectUFM_C use_snd t1 t2
438 intersectUFM_C f EmptyUFM _ = EmptyUFM
439 intersectUFM_C f _ EmptyUFM = EmptyUFM
440 intersectUFM_C f fm1 fm2 = intersect_trees fm1 fm2
442 intersect_trees (LeafUFM i a) t2 =
445 Just b -> mkLeafUFM i (f a b)
447 intersect_trees t1 (LeafUFM i a) =
450 Just b -> mkLeafUFM i (f b a)
452 intersect_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
454 (ask_about_common_ancestor
458 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
461 -- / \ + / \ ==> EmptyUFM
466 intersect_branches (NewRoot nd _) = EmptyUFM
472 -- t1 t2 t1' t2' t1 x t1' t2 x t2'
474 intersect_branches (SameRoot)
475 = mkSSNodeUFM (NodeUFMData j p)
476 (intersect_trees t1 t1')
477 (intersect_trees t2 t2')
478 -- Now the 4 different other ways; all like this:
480 -- Given j >^ j' (and, say, j > j')
484 -- t1 t2 t1' t2' t1' t2'
486 -- This does cut down the search space quite a bit.
488 intersect_branches (LeftRoot Leftt)
489 = intersect_trees t1 right_t
490 intersect_branches (LeftRoot Rightt)
491 = intersect_trees t2 right_t
492 intersect_branches (RightRoot Leftt)
493 = intersect_trees left_t t1'
494 intersect_branches (RightRoot Rightt)
495 = intersect_trees left_t t2'
497 intersect_trees x y = panic ("EmptyUFM found when intersecting trees")
500 Now the usual set of `collection' operators, like map, fold, etc.
503 foldUFM f a (NodeUFM _ _ t1 t2) = foldUFM f (foldUFM f a t2) t1
504 foldUFM f a (LeafUFM _ obj) = f obj a
505 foldUFM f a EmptyUFM = a
509 mapUFM fn EmptyUFM = EmptyUFM
510 mapUFM fn fm = map_tree fn fm
512 filterUFM fn EmptyUFM = EmptyUFM
513 filterUFM fn fm = filter_tree fn fm
516 Note, this takes a long time, O(n), but
517 because we dont want to do this very often, we put up with this.
518 O'rable, but how often do we look at the size of
523 sizeUFM (NodeUFM _ _ t1 t2) = sizeUFM t1 + sizeUFM t2
524 sizeUFM (LeafUFM _ _) = 1
526 isNullUFM EmptyUFM = True
530 looking up in a hurry is the {\em whole point} of this binary tree lark.
531 Lookup up a binary tree is easy (and fast).
534 elemUFM key fm = case lookUp fm (u2i (uniqueOf key)) of
538 lookupUFM fm key = lookUp fm (u2i (uniqueOf key))
539 lookupUFM_Directly fm key = lookUp fm (u2i key)
541 lookupWithDefaultUFM fm deflt key
542 = case lookUp fm (u2i (uniqueOf key)) of
546 lookupWithDefaultUFM_Directly fm deflt key
547 = case lookUp fm (u2i key) of
551 lookUp EmptyUFM _ = Nothing
552 lookUp fm i = lookup_tree fm
554 lookup_tree :: UniqFM a -> Maybe a
556 lookup_tree (LeafUFM j b)
558 | otherwise = Nothing
559 lookup_tree (NodeUFM j p t1 t2)
560 | j _GT_ i = lookup_tree t1
561 | otherwise = lookup_tree t2
563 lookup_tree EmptyUFM = panic "lookup Failed"
566 folds are *wonderful* things.
569 eltsUFM fm = foldUFM (:) [] fm
571 ufmToList fm = fold_tree (\ iu elt rest -> (mkUniqueGrimily iu, elt) : rest) [] fm
573 keysUFM fm = fold_tree (\ iu elt rest -> IBOX(iu) : rest) [] fm
575 fold_tree f a (NodeUFM _ _ t1 t2) = fold_tree f (fold_tree f a t2) t1
576 fold_tree f a (LeafUFM iu obj) = f iu obj a
577 fold_tree f a EmptyUFM = a
580 %************************************************************************
582 \subsubsection{The @UniqFM@ type, and its functions}
584 %************************************************************************
586 You should always use these to build the tree.
587 There are 4 versions of mkNodeUFM, depending on
588 the strictness of the two sub-tree arguments.
589 The strictness is used *both* to prune out
590 empty trees, *and* to improve performance,
591 stoping needless thunks lying around.
592 The rule of thumb (from experence with these trees)
593 is make thunks strict, but data structures lazy.
594 If in doubt, use mkSSNodeUFM, which has the `strongest'
595 functionality, but may do a few needless evaluations.
598 mkLeafUFM :: FAST_INT -> a -> UniqFM a
599 mkLeafUFM i a = LeafUFM i a
601 -- The *ONLY* ways of building a NodeUFM.
603 mkSSNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
604 mkSSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
605 mkSSNodeUFM (NodeUFMData j p) t1 t2
606 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
609 mkSLNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
610 mkSLNodeUFM (NodeUFMData j p) t1 t2
611 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
614 mkLSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
615 mkLSNodeUFM (NodeUFMData j p) t1 t2
616 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
619 mkLLNodeUFM (NodeUFMData j p) t1 t2
620 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
630 correctNodeUFM j p t1 t2
631 = correct (j-p) (j-1) p t1 && correct j ((j-1)+p) p t2
633 correct low high _ (LeafUFM i _)
634 = low <= IBOX(i) && IBOX(i) <= high
635 correct low high above_p (NodeUFM j p _ _)
636 = low <= IBOX(j) && IBOX(j) <= high && above_p > IBOX(p)
637 correct _ _ _ EmptyUFM = panic "EmptyUFM stored inside a tree"
640 Note: doing SAT on this by hand seems to make it worse. Todo: Investigate,
641 and if necessary do $\lambda$ lifting on our functions that are bound.
651 insert_ele f EmptyUFM i new = mkLeafUFM i new
653 insert_ele f (LeafUFM j old) i new
655 mkLLNodeUFM (getCommonNodeUFMData
660 | j _EQ_ i = mkLeafUFM j (f old new)
662 mkLLNodeUFM (getCommonNodeUFMData
668 insert_ele f n@(NodeUFM j p t1 t2) i a
670 = if (i _GE_ (j _SUB_ p))
671 then mkSLNodeUFM (NodeUFMData j p) (insert_ele f t1 i a) t2
672 else mkLLNodeUFM (getCommonNodeUFMData
678 = if (i _LE_ ((j _SUB_ ILIT(1)) _ADD_ p))
679 then mkLSNodeUFM (NodeUFMData j p) t1 (insert_ele f t2 i a)
680 else mkLLNodeUFM (getCommonNodeUFMData
690 map_tree f (NodeUFM j p t1 t2)
691 = mkSSNodeUFM (NodeUFMData j p) (map_tree f t1) (map_tree f t2)
692 map_tree f (LeafUFM i obj)
693 = mkLeafUFM i (f obj)
695 map_tree f _ = panic "map_tree failed"
699 filter_tree f nd@(NodeUFM j p t1 t2)
700 = mkSSNodeUFM (NodeUFMData j p) (filter_tree f t1) (filter_tree f t2)
702 filter_tree f lf@(LeafUFM i obj)
704 | otherwise = EmptyUFM
705 filter_tree f _ = panic "filter_tree failed"
708 %************************************************************************
710 \subsubsection{The @UniqFM@ type, and signatures for the functions}
712 %************************************************************************
716 This is the information that is held inside a NodeUFM, packaged up for
721 = NodeUFMData FAST_INT
725 This is the information used when computing new NodeUFMs.
728 data Side = Leftt | Rightt -- NB: avoid 1.3 names "Left" and "Right"
730 = LeftRoot Side -- which side is the right down ?
731 | RightRoot Side -- which side is the left down ?
732 | SameRoot -- they are the same !
733 | NewRoot NodeUFMData -- here's the new, common, root
734 Bool -- do you need to swap left and right ?
737 This specifies the relationship between NodeUFMData and CalcNodeUFMData.
740 indexToRoot :: FAST_INT -> NodeUFMData
744 l = (ILIT(1) :: FAST_INT)
746 NodeUFMData (((i `shiftR_` l) `shiftL_` l) _ADD_ ILIT(1)) l
748 getCommonNodeUFMData :: NodeUFMData -> NodeUFMData -> NodeUFMData
750 getCommonNodeUFMData (NodeUFMData i p) (NodeUFMData i2 p2)
751 | p _EQ_ p2 = getCommonNodeUFMData_ p j j2
752 | p _LT_ p2 = getCommonNodeUFMData_ p2 (j _QUOT_ (p2 _QUOT_ p)) j2
753 | otherwise = getCommonNodeUFMData_ p j (j2 _QUOT_ (p _QUOT_ p2))
755 l = (ILIT(1) :: FAST_INT)
756 j = i _QUOT_ (p `shiftL_` l)
757 j2 = i2 _QUOT_ (p2 `shiftL_` l)
759 getCommonNodeUFMData_ :: FAST_INT -> FAST_INT -> FAST_INT -> NodeUFMData
761 getCommonNodeUFMData_ p j j_
763 = NodeUFMData (((j `shiftL_` l) _ADD_ l) _MUL_ p) p
765 = getCommonNodeUFMData_ (p `shiftL_` l) (j `shiftR_` l) (j_ `shiftR_` l)
767 ask_about_common_ancestor :: NodeUFMData -> NodeUFMData -> CommonRoot
769 ask_about_common_ancestor x@(NodeUFMData j p) y@(NodeUFMData j2 p2)
770 | j _EQ_ j2 = SameRoot
772 = case getCommonNodeUFMData x y of
773 nd@(NodeUFMData j3 p3)
774 | j3 _EQ_ j -> LeftRoot (decideSide (j _GT_ j2))
775 | j3 _EQ_ j2 -> RightRoot (decideSide (j _LT_ j2))
776 | otherwise -> NewRoot nd (j _GT_ j2)
778 decideSide :: Bool -> Side
779 decideSide True = Leftt
780 decideSide False = Rightt
783 This might be better in Util.lhs ?
786 Now the bit twiddling functions.
788 shiftL_ :: FAST_INT -> FAST_INT -> FAST_INT
789 shiftR_ :: FAST_INT -> FAST_INT -> FAST_INT
791 #if __GLASGOW_HASKELL__
792 {-# INLINE shiftL_ #-}
793 {-# INLINE shiftR_ #-}
794 shiftL_ n p = word2Int#((int2Word# n) `shiftL#` p)
795 shiftR_ n p = word2Int#((int2Word# n) `shiftr` p)
797 shiftr x y = shiftRA# x y
800 shiftL_ n p = n * (2 ^ p)
801 shiftR_ n p = n `quot` (2 ^ p)
807 use_snd :: a -> b -> b