2 % (c) The University of Glasgow 2006
3 % (c) The AQUA Project, Glasgow University, 1994-1998
6 UniqFM: Specialised finite maps, for things with @Uniques@
8 Based on @FiniteMaps@ (as you would expect).
10 Basically, the things need to be in class @Uniquable@, and we use the
11 @getUnique@ method to grab their @Uniques@.
13 (A similar thing to @UniqSet@, as opposed to @Set@.)
16 {-# OPTIONS -Wall -fno-warn-name-shadowing #-}
18 -- * Unique-keyed mappings
19 UniqFM(..), -- abstract type
20 -- (de-abstracted for MachRegs.trivColorable optimisation BL 2007/09)
22 -- ** Manipulating those mappings
29 addToUFM,addToUFM_C,addToUFM_Acc,
30 addListToUFM,addListToUFM_C,
32 addListToUFM_Directly,
42 foldUFM, foldUFM_Directly,
44 elemUFM, elemUFM_Directly,
45 filterUFM, filterUFM_Directly,
49 lookupUFM, lookupUFM_Directly,
50 lookupWithDefaultUFM, lookupWithDefaultUFM_Directly,
55 #include "HsVersions.h"
57 import Unique ( Uniquable(..), Unique, getKeyFastInt, mkUniqueGrimily )
58 import Maybes ( maybeToBool )
63 %************************************************************************
65 \subsection{The @UniqFM@ type, and signatures for the functions}
67 %************************************************************************
69 We use @FiniteMaps@, with a (@getUnique@-able) @Unique@ as ``key''.
72 emptyUFM :: UniqFM elt
73 isNullUFM :: UniqFM elt -> Bool
74 unitUFM :: Uniquable key => key -> elt -> UniqFM elt
75 unitDirectlyUFM -- got the Unique already
76 :: Unique -> elt -> UniqFM elt
77 listToUFM :: Uniquable key => [(key,elt)] -> UniqFM elt
79 :: [(Unique, elt)] -> UniqFM elt
80 listToUFM_C :: Uniquable key => (elt -> elt -> elt)
84 addToUFM :: Uniquable key => UniqFM elt -> key -> elt -> UniqFM elt
85 addListToUFM :: Uniquable key => UniqFM elt -> [(key,elt)] -> UniqFM elt
86 addListToUFM_Directly :: UniqFM elt -> [(Unique,elt)] -> UniqFM elt
88 :: UniqFM elt -> Unique -> elt -> UniqFM elt
90 addToUFM_C :: Uniquable key => (elt -> elt -> elt) -- old -> new -> result
93 -> UniqFM elt -- result
95 addToUFM_Acc :: Uniquable key =>
96 (elt -> elts -> elts) -- Add to existing
97 -> (elt -> elts) -- New element
100 -> UniqFM elts -- result
102 addListToUFM_C :: Uniquable key => (elt -> elt -> elt)
103 -> UniqFM elt -> [(key,elt)]
106 delFromUFM :: Uniquable key => UniqFM elt -> key -> UniqFM elt
107 delListFromUFM :: Uniquable key => UniqFM elt -> [key] -> UniqFM elt
108 delFromUFM_Directly :: UniqFM elt -> Unique -> UniqFM elt
110 plusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
112 plusUFM_C :: (elt -> elt -> elt)
113 -> UniqFM elt -> UniqFM elt -> UniqFM elt
115 minusUFM :: UniqFM elt1 -> UniqFM elt2 -> UniqFM elt1
117 intersectUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
118 intersectUFM_C :: (elt1 -> elt2 -> elt3)
119 -> UniqFM elt1 -> UniqFM elt2 -> UniqFM elt3
120 intersectsUFM :: UniqFM elt1 -> UniqFM elt2 -> Bool
122 foldUFM :: (elt -> a -> a) -> a -> UniqFM elt -> a
123 foldUFM_Directly:: (Unique -> elt -> a -> a) -> a -> UniqFM elt -> a
124 mapUFM :: (elt1 -> elt2) -> UniqFM elt1 -> UniqFM elt2
125 filterUFM :: (elt -> Bool) -> UniqFM elt -> UniqFM elt
126 filterUFM_Directly :: (Unique -> elt -> Bool) -> UniqFM elt -> UniqFM elt
128 sizeUFM :: UniqFM elt -> Int
129 hashUFM :: UniqFM elt -> Int
130 elemUFM :: Uniquable key => key -> UniqFM elt -> Bool
131 elemUFM_Directly:: Unique -> UniqFM elt -> Bool
133 lookupUFM :: Uniquable key => UniqFM elt -> key -> Maybe elt
134 lookupUFM_Directly -- when you've got the Unique already
135 :: UniqFM elt -> Unique -> Maybe elt
137 :: Uniquable key => UniqFM elt -> elt -> key -> elt
138 lookupWithDefaultUFM_Directly
139 :: UniqFM elt -> elt -> Unique -> elt
141 keysUFM :: UniqFM elt -> [Unique] -- Get the keys
142 eltsUFM :: UniqFM elt -> [elt]
143 ufmToList :: UniqFM elt -> [(Unique, elt)]
146 %************************************************************************
148 \subsection{The @IdFinMap@ and @TyVarFinMap@ specialisations for Ids/TyVars}
150 %************************************************************************
153 -- Turn off for now, these need to be updated (SDM 4/98)
156 #ifdef __GLASGOW_HASKELL__
157 -- I don't think HBC was too happy about this (WDP 94/10)
160 addListToUFM :: UniqFM elt -> [(Name, elt)] -> UniqFM elt
163 addListToUFM_C :: (elt -> elt -> elt) -> UniqFM elt -> [(Name, elt)] -> UniqFM elt
166 addToUFM :: UniqFM elt -> Unique -> elt -> UniqFM elt
169 listToUFM :: [(Unique, elt)] -> UniqFM elt
172 lookupUFM :: UniqFM elt -> Name -> Maybe elt
173 , UniqFM elt -> Unique -> Maybe elt
176 #endif /* __GLASGOW_HASKELL__ */
180 %************************************************************************
182 \subsection{Andy Gill's underlying @UniqFM@ machinery}
184 %************************************************************************
186 ``Uniq Finite maps'' are the heart and soul of the compiler's
187 lookup-tables/environments. Important stuff! It works well with
188 Dense and Sparse ranges.
189 Both @Uq@ Finite maps and @Hash@ Finite Maps
190 are built ontop of Int Finite Maps.
192 This code is explained in the paper:
194 A Gill, S Peyton Jones, B O'Sullivan, W Partain and Aqua Friends
195 "A Cheap balancing act that grows on a tree"
196 Glasgow FP Workshop, Sep 1994, pp??-??
199 %************************************************************************
201 \subsubsection{The @UniqFM@ type, and signatures for the functions}
203 %************************************************************************
205 First, the DataType itself; which is either a Node, a Leaf, or an Empty.
208 -- | @UniqFM a@ is a mapping from Unique to @a@. DO NOT use these constructors
209 -- directly unless you live in this module!
212 | LeafUFM !FastInt ele
213 | NodeUFM !FastInt -- the switching
214 !FastInt -- the delta
217 -- INVARIANT: the children of a NodeUFM are never EmptyUFMs
220 -- for debugging only :-)
221 instance Outputable (UniqFM a) where
222 ppr(NodeUFM a b t1 t2) =
223 sep [text "NodeUFM " <+> int IBOX(a) <+> int IBOX(b),
224 nest 1 (parens (ppr t1)),
225 nest 1 (parens (ppr t2))]
226 ppr (LeafUFM x a) = text "LeafUFM " <+> int IBOX(x)
227 ppr (EmptyUFM) = empty
229 -- and when not debugging the package itself...
230 instance Outputable a => Outputable (UniqFM a) where
231 ppr ufm = ppr (ufmToList ufm)
234 %************************************************************************
236 \subsubsection{The @UniqFM@ functions}
238 %************************************************************************
240 First the ways of building a UniqFM.
244 unitUFM key elt = mkLeafUFM (getKeyFastInt (getUnique key)) elt
245 unitDirectlyUFM key elt = mkLeafUFM (getKeyFastInt key) elt
247 listToUFM key_elt_pairs
248 = addListToUFM_C use_snd EmptyUFM key_elt_pairs
250 listToUFM_Directly uniq_elt_pairs
251 = addListToUFM_directly_C use_snd EmptyUFM uniq_elt_pairs
253 listToUFM_C combiner key_elt_pairs
254 = addListToUFM_C combiner EmptyUFM key_elt_pairs
257 Now ways of adding things to UniqFMs.
259 There is an alternative version of @addListToUFM_C@, that uses @plusUFM@,
260 but the semantics of this operation demands a linear insertion;
261 perhaps the version without the combinator function
262 could be optimised using it.
265 addToUFM fm key elt = addToUFM_C use_snd fm key elt
267 addToUFM_Directly fm u elt = insert_ele use_snd fm (getKeyFastInt u) elt
269 addToUFM_C combiner fm key elt
270 = insert_ele combiner fm (getKeyFastInt (getUnique key)) elt
272 addToUFM_Acc add unit fm key item
273 = insert_ele combiner fm (getKeyFastInt (getUnique key)) (unit item)
275 combiner old _unit_item = add item old
277 addListToUFM fm key_elt_pairs = addListToUFM_C use_snd fm key_elt_pairs
278 addListToUFM_Directly fm uniq_elt_pairs = addListToUFM_directly_C use_snd fm uniq_elt_pairs
280 addListToUFM_C combiner fm key_elt_pairs
281 = foldl (\ fm (k, e) -> insert_ele combiner fm (getKeyFastInt (getUnique k)) e)
284 addListToUFM_directly_C :: (elt -> elt -> elt) -> UniqFM elt -> [(Unique,elt)] -> UniqFM elt
285 addListToUFM_directly_C combiner fm uniq_elt_pairs
286 = foldl (\ fm (k, e) -> insert_ele combiner fm (getKeyFastInt k) e)
290 Now ways of removing things from UniqFM.
293 delListFromUFM fm lst = foldl delFromUFM fm lst
295 delFromUFM fm key = delete fm (getKeyFastInt (getUnique key))
296 delFromUFM_Directly fm u = delete fm (getKeyFastInt u)
298 delete :: UniqFM a -> FastInt -> UniqFM a
299 delete EmptyUFM _ = EmptyUFM
300 delete fm key = del_ele fm
302 del_ele :: UniqFM a -> UniqFM a
304 del_ele lf@(LeafUFM j _)
305 | j ==# key = EmptyUFM
306 | otherwise = lf -- no delete!
308 del_ele (NodeUFM j p t1 t2)
310 = mkSLNodeUFM (NodeUFMData j p) (del_ele t1) t2
312 = mkLSNodeUFM (NodeUFMData j p) t1 (del_ele t2)
314 del_ele _ = panic "Found EmptyUFM FM when rec-deleting"
317 Now ways of adding two UniqFM's together.
320 plusUFM tr1 tr2 = plusUFM_C use_snd tr1 tr2
322 plusUFM_C _ EmptyUFM tr = tr
323 plusUFM_C _ tr EmptyUFM = tr
324 plusUFM_C f fm1 fm2 = mix_trees fm1 fm2
326 mix_trees (LeafUFM i a) t2 = insert_ele (flip f) t2 i a
327 mix_trees t1 (LeafUFM i a) = insert_ele f t1 i a
329 mix_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
331 (ask_about_common_ancestor
335 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
339 -- t1 t2 t1' t2' j j'
344 mix_branches (NewRoot nd False)
345 = mkLLNodeUFM nd left_t right_t
346 mix_branches (NewRoot nd True)
347 = mkLLNodeUFM nd right_t left_t
353 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
355 mix_branches (SameRoot)
356 = mkSSNodeUFM (NodeUFMData j p)
359 -- Now the 4 different other ways; all like this:
361 -- Given j >^ j' (and, say, j > j')
365 -- t1 t2 t1' t2' t1 t2 + j'
368 mix_branches (LeftRoot Leftt) -- | trace "LL" True
371 (mix_trees t1 right_t)
374 mix_branches (LeftRoot Rightt) -- | trace "LR" True
378 (mix_trees t2 right_t)
380 mix_branches (RightRoot Leftt) -- | trace "RL" True
383 (mix_trees left_t t1')
386 mix_branches (RightRoot Rightt) -- | trace "RR" True
390 (mix_trees left_t t2')
392 mix_trees _ _ = panic "EmptyUFM found when inserting into plusInt"
395 And ways of subtracting them. First the base cases,
396 then the full D&C approach.
399 minusUFM EmptyUFM _ = EmptyUFM
400 minusUFM t1 EmptyUFM = t1
401 minusUFM fm1 fm2 = minus_trees fm1 fm2
404 -- Notice the asymetry of subtraction
406 minus_trees lf@(LeafUFM i _a) t2 =
411 minus_trees t1 (LeafUFM i _) = delete t1 i
413 minus_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
415 (ask_about_common_ancestor
419 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
423 -- t1 t2 t1' t2' t1 t2
428 minus_branches (NewRoot _ _) = left_t
434 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
436 minus_branches (SameRoot)
437 = mkSSNodeUFM (NodeUFMData j p)
440 -- Now the 4 different other ways; all like this:
441 -- again, with asymatry
444 -- The left is above the right
446 minus_branches (LeftRoot Leftt)
449 (minus_trees t1 right_t)
451 minus_branches (LeftRoot Rightt)
455 (minus_trees t2 right_t)
458 -- The right is above the left
460 minus_branches (RightRoot Leftt)
461 = minus_trees left_t t1'
462 minus_branches (RightRoot Rightt)
463 = minus_trees left_t t2'
465 minus_trees _ _ = panic "EmptyUFM found when insering into plusInt"
468 And taking the intersection of two UniqFM's.
471 intersectUFM t1 t2 = intersectUFM_C use_snd t1 t2
472 intersectsUFM t1 t2 = isNullUFM (intersectUFM_C (\ _ _ -> error "urk") t1 t2)
474 intersectUFM_C _ EmptyUFM _ = EmptyUFM
475 intersectUFM_C _ _ EmptyUFM = EmptyUFM
476 intersectUFM_C f fm1 fm2 = intersect_trees fm1 fm2
478 intersect_trees (LeafUFM i a) t2 =
481 Just b -> mkLeafUFM i (f a b)
483 intersect_trees t1 (LeafUFM i a) =
486 Just b -> mkLeafUFM i (f b a)
488 intersect_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
490 (ask_about_common_ancestor
494 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
497 -- / \ + / \ ==> EmptyUFM
502 intersect_branches (NewRoot _nd _) = EmptyUFM
508 -- t1 t2 t1' t2' t1 x t1' t2 x t2'
510 intersect_branches (SameRoot)
511 = mkSSNodeUFM (NodeUFMData j p)
512 (intersect_trees t1 t1')
513 (intersect_trees t2 t2')
514 -- Now the 4 different other ways; all like this:
516 -- Given j >^ j' (and, say, j > j')
520 -- t1 t2 t1' t2' t1' t2'
522 -- This does cut down the search space quite a bit.
524 intersect_branches (LeftRoot Leftt)
525 = intersect_trees t1 right_t
526 intersect_branches (LeftRoot Rightt)
527 = intersect_trees t2 right_t
528 intersect_branches (RightRoot Leftt)
529 = intersect_trees left_t t1'
530 intersect_branches (RightRoot Rightt)
531 = intersect_trees left_t t2'
533 intersect_trees _ _ = panic ("EmptyUFM found when intersecting trees")
536 Now the usual set of `collection' operators, like map, fold, etc.
539 foldUFM f a (NodeUFM _ _ t1 t2) = foldUFM f (foldUFM f a t2) t1
540 foldUFM f a (LeafUFM _ obj) = f obj a
541 foldUFM _ a EmptyUFM = a
545 mapUFM _fn EmptyUFM = EmptyUFM
546 mapUFM fn fm = map_tree fn fm
548 filterUFM _fn EmptyUFM = EmptyUFM
549 filterUFM fn fm = filter_tree (\_ e -> fn e) fm
551 filterUFM_Directly _fn EmptyUFM = EmptyUFM
552 filterUFM_Directly fn fm = filter_tree pred fm
554 pred i e = fn (mkUniqueGrimily (iBox i)) e
557 Note, this takes a long time, O(n), but
558 because we dont want to do this very often, we put up with this.
559 O'rable, but how often do we look at the size of
564 sizeUFM (NodeUFM _ _ t1 t2) = sizeUFM t1 + sizeUFM t2
565 sizeUFM (LeafUFM _ _) = 1
567 isNullUFM EmptyUFM = True
570 -- hashing is used in VarSet.uniqAway, and should be fast
571 -- We use a cheap and cheerful method for now
573 hashUFM (NodeUFM n _ _ _) = iBox n
574 hashUFM (LeafUFM n _) = iBox n
577 looking up in a hurry is the {\em whole point} of this binary tree lark.
578 Lookup up a binary tree is easy (and fast).
581 elemUFM key fm = maybeToBool (lookupUFM fm key)
582 elemUFM_Directly key fm = maybeToBool (lookupUFM_Directly fm key)
584 lookupUFM fm key = lookUp fm (getKeyFastInt (getUnique key))
585 lookupUFM_Directly fm key = lookUp fm (getKeyFastInt key)
587 lookupWithDefaultUFM fm deflt key
588 = case lookUp fm (getKeyFastInt (getUnique key)) of
592 lookupWithDefaultUFM_Directly fm deflt key
593 = case lookUp fm (getKeyFastInt key) of
597 lookUp :: UniqFM a -> FastInt -> Maybe a
598 lookUp EmptyUFM _ = Nothing
599 lookUp fm i = lookup_tree fm
601 lookup_tree :: UniqFM a -> Maybe a
603 lookup_tree (LeafUFM j b)
605 | otherwise = Nothing
606 lookup_tree (NodeUFM j _ t1 t2)
607 | j ># i = lookup_tree t1
608 | otherwise = lookup_tree t2
610 lookup_tree EmptyUFM = panic "lookup Failed"
613 folds are *wonderful* things.
616 eltsUFM fm = foldUFM (:) [] fm
617 keysUFM fm = foldUFM_Directly (\u _ l -> u : l) [] fm
618 ufmToList fm = foldUFM_Directly (\u e l -> (u, e) : l) [] fm
619 foldUFM_Directly f = fold_tree (\iu e a -> f (mkUniqueGrimily (iBox iu)) e a)
621 fold_tree :: (FastInt -> elt -> a -> a) -> a -> UniqFM elt -> a
622 fold_tree f a (NodeUFM _ _ t1 t2) = fold_tree f (fold_tree f a t2) t1
623 fold_tree f a (LeafUFM iu obj) = f iu obj a
624 fold_tree _ a EmptyUFM = a
627 %************************************************************************
629 \subsubsection{The @UniqFM@ type, and its functions}
631 %************************************************************************
633 You should always use these to build the tree.
634 There are 4 versions of mkNodeUFM, depending on
635 the strictness of the two sub-tree arguments.
636 The strictness is used *both* to prune out
637 empty trees, *and* to improve performance,
638 stoping needless thunks lying around.
639 The rule of thumb (from experence with these trees)
640 is make thunks strict, but data structures lazy.
641 If in doubt, use mkSSNodeUFM, which has the `strongest'
642 functionality, but may do a few needless evaluations.
645 mkLeafUFM :: FastInt -> a -> UniqFM a
647 ASSERT (iBox i >= 0) -- Note [Uniques must be positive]
650 -- The *ONLY* ways of building a NodeUFM.
652 mkSSNodeUFM, mkSLNodeUFM, mkLSNodeUFM, mkLLNodeUFM ::
653 NodeUFMData -> UniqFM a -> UniqFM a -> UniqFM a
655 mkSSNodeUFM (NodeUFMData _ _) EmptyUFM t2 = t2
656 mkSSNodeUFM (NodeUFMData _ _) t1 EmptyUFM = t1
657 mkSSNodeUFM (NodeUFMData j p) t1 t2
658 = ASSERT(correctNodeUFM (iBox j) (iBox p) t1 t2)
661 mkSLNodeUFM (NodeUFMData _ _) EmptyUFM t2 = t2
662 mkSLNodeUFM (NodeUFMData j p) t1 t2
663 = ASSERT(correctNodeUFM (iBox j) (iBox p) t1 t2)
666 mkLSNodeUFM (NodeUFMData _ _) t1 EmptyUFM = t1
667 mkLSNodeUFM (NodeUFMData j p) t1 t2
668 = ASSERT(correctNodeUFM (iBox j) (iBox p) t1 t2)
671 mkLLNodeUFM (NodeUFMData j p) t1 t2
672 = ASSERT(correctNodeUFM (iBox j) (iBox p) t1 t2)
682 correctNodeUFM j p t1 t2
683 = correct (j-p) (j-1) p t1 && correct j ((j-1)+p) p t2
685 correct low high _ (LeafUFM i _)
686 = low <= iBox i && iBox i <= high
687 correct low high above_p (NodeUFM j p _ _)
688 = low <= iBox j && iBox j <= high && above_p > iBox p
689 correct _ _ _ EmptyUFM = panic "EmptyUFM stored inside a tree"
692 Note: doing SAT on this by hand seems to make it worse. Todo: Investigate,
693 and if necessary do $\lambda$ lifting on our functions that are bound.
697 :: (a -> a -> a) -- old -> new -> result
703 insert_ele _f EmptyUFM i new = mkLeafUFM i new
705 insert_ele f (LeafUFM j old) i new
707 mkLLNodeUFM (getCommonNodeUFMData
712 | j ==# i = mkLeafUFM j $ f old new
714 mkLLNodeUFM (getCommonNodeUFMData
720 insert_ele f n@(NodeUFM j p t1 t2) i a
722 = if (i >=# (j -# p))
723 then mkSLNodeUFM (NodeUFMData j p) (insert_ele f t1 i a) t2
724 else mkLLNodeUFM (getCommonNodeUFMData
730 = if (i <=# ((j -# _ILIT(1)) +# p))
731 then mkLSNodeUFM (NodeUFMData j p) t1 (insert_ele f t2 i a)
732 else mkLLNodeUFM (getCommonNodeUFMData
742 map_tree :: (a -> b) -> UniqFM a -> UniqFM b
743 map_tree f (NodeUFM j p t1 t2)
744 = mkLLNodeUFM (NodeUFMData j p) (map_tree f t1) (map_tree f t2)
745 -- NB. lazy! we know the tree is well-formed.
746 map_tree f (LeafUFM i obj)
747 = mkLeafUFM i (f obj)
748 map_tree _ _ = panic "map_tree failed"
752 filter_tree :: (FastInt -> a -> Bool) -> UniqFM a -> UniqFM a
753 filter_tree f (NodeUFM j p t1 t2)
754 = mkSSNodeUFM (NodeUFMData j p) (filter_tree f t1) (filter_tree f t2)
756 filter_tree f lf@(LeafUFM i obj)
758 | otherwise = EmptyUFM
759 filter_tree _ _ = panic "filter_tree failed"
762 %************************************************************************
764 \subsubsection{The @UniqFM@ type, and signatures for the functions}
766 %************************************************************************
770 This is the information that is held inside a NodeUFM, packaged up for
775 = NodeUFMData FastInt
779 This is the information used when computing new NodeUFMs.
782 data Side = Leftt | Rightt -- NB: avoid 1.3 names "Left" and "Right"
784 = LeftRoot Side -- which side is the right down ?
785 | RightRoot Side -- which side is the left down ?
786 | SameRoot -- they are the same !
787 | NewRoot NodeUFMData -- here's the new, common, root
788 Bool -- do you need to swap left and right ?
791 This specifies the relationship between NodeUFMData and CalcNodeUFMData.
794 indexToRoot :: FastInt -> NodeUFMData
797 = NodeUFMData ((shiftL1 (shiftR1 i)) +# _ILIT(1)) (_ILIT(1))
799 getCommonNodeUFMData :: NodeUFMData -> NodeUFMData -> NodeUFMData
801 getCommonNodeUFMData (NodeUFMData i p) (NodeUFMData i2 p2)
802 | p ==# p2 = getCommonNodeUFMData_ p j j2
803 | p <# p2 = getCommonNodeUFMData_ p2 (j `quotFastInt` (p2 `quotFastInt` p)) j2
804 | otherwise = getCommonNodeUFMData_ p j (j2 `quotFastInt` (p `quotFastInt` p2))
806 j = i `quotFastInt` (shiftL1 p)
807 j2 = i2 `quotFastInt` (shiftL1 p2)
809 getCommonNodeUFMData_ :: FastInt -> FastInt -> FastInt -> NodeUFMData
811 getCommonNodeUFMData_ p j j_
813 = NodeUFMData (((shiftL1 j) +# _ILIT(1)) *# p) p
815 = getCommonNodeUFMData_ (shiftL1 p) (shiftR1 j) (shiftR1 j_)
817 ask_about_common_ancestor :: NodeUFMData -> NodeUFMData -> CommonRoot
819 ask_about_common_ancestor x@(NodeUFMData j _p) y@(NodeUFMData j2 _p2)
820 | j ==# j2 = SameRoot
822 = case getCommonNodeUFMData x y of
823 nd@(NodeUFMData j3 _p3)
824 | j3 ==# j -> LeftRoot (decideSide (j ># j2))
825 | j3 ==# j2 -> RightRoot (decideSide (j <# j2))
826 | otherwise -> NewRoot nd (j ># j2)
828 decideSide :: Bool -> Side
829 decideSide True = Leftt
830 decideSide False = Rightt
833 This might be better in Util.lhs ?
836 Now the bit twiddling functions.
838 shiftL1 :: FastInt -> FastInt
839 shiftR1 :: FastInt -> FastInt
841 {-# INLINE shiftL1 #-}
842 {-# INLINE shiftR1 #-}
844 shiftL1 n = n `shiftLFastInt` _ILIT(1)
845 shiftR1 n = n `shiftR_FastInt` _ILIT(1)
849 use_snd :: a -> b -> b
853 {- Note [Uniques must be positive]
854 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
855 The getCommonNodeUFMData function assumes that the nodes use
856 positive uniques. Specifically, the inner `loop' shifts the
857 low bits out of two uniques until the shifted uniques are the same.
858 At the same time, it computes a new delta, by shifting
861 The failure case I (JPD) encountered:
862 If one of the uniques is negative, the shifting may continue
863 until all 64 bits have been shifted out, resulting in a new delta
864 of 0, which is wrong and can trigger later assertion failures.
866 Where do the negative uniques come from? Both Simom M and
867 I have run into this problem when hashing a data structure.
868 In both cases, we have avoided the problem by ensuring that
869 the hashes remain positive.