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@.)
17 UniqFM, -- abstract type
24 addToUFM,addToUFM_C,addToUFM_Acc,
25 addListToUFM,addListToUFM_C,
27 addListToUFM_Directly,
39 elemUFM, elemUFM_Directly,
40 filterUFM, filterUFM_Directly,
44 lookupUFM, lookupUFM_Directly,
45 lookupWithDefaultUFM, lookupWithDefaultUFM_Directly,
50 #include "HsVersions.h"
52 import Unique ( Uniquable(..), Unique, getKey#, mkUniqueGrimily )
53 import Maybes ( maybeToBool )
57 import GHC.Exts -- Lots of Int# operations
60 %************************************************************************
62 \subsection{The @UniqFM@ type, and signatures for the functions}
64 %************************************************************************
66 We use @FiniteMaps@, with a (@getUnique@-able) @Unique@ as ``key''.
69 emptyUFM :: UniqFM elt
70 isNullUFM :: UniqFM elt -> Bool
71 unitUFM :: Uniquable key => key -> elt -> UniqFM elt
72 unitDirectlyUFM -- got the Unique already
73 :: Unique -> elt -> UniqFM elt
74 listToUFM :: Uniquable key => [(key,elt)] -> UniqFM elt
76 :: [(Unique, elt)] -> UniqFM elt
78 addToUFM :: Uniquable key => UniqFM elt -> key -> elt -> UniqFM elt
79 addListToUFM :: Uniquable key => UniqFM elt -> [(key,elt)] -> UniqFM elt
81 :: UniqFM elt -> Unique -> elt -> UniqFM elt
83 addToUFM_C :: Uniquable key => (elt -> elt -> elt) -- old -> new -> result
86 -> UniqFM elt -- result
88 addToUFM_Acc :: Uniquable key =>
89 (elt -> elts -> elts) -- Add to existing
90 -> (elt -> elts) -- New element
93 -> UniqFM elts -- result
95 addListToUFM_C :: Uniquable key => (elt -> elt -> elt)
96 -> UniqFM elt -> [(key,elt)]
99 delFromUFM :: Uniquable key => UniqFM elt -> key -> UniqFM elt
100 delListFromUFM :: Uniquable key => UniqFM elt -> [key] -> UniqFM elt
101 delFromUFM_Directly :: UniqFM elt -> Unique -> UniqFM elt
103 plusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
105 plusUFM_C :: (elt -> elt -> elt)
106 -> UniqFM elt -> UniqFM elt -> UniqFM elt
108 minusUFM :: UniqFM elt1 -> UniqFM elt2 -> UniqFM elt1
110 intersectUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
111 intersectUFM_C :: (elt1 -> elt2 -> elt3)
112 -> UniqFM elt1 -> UniqFM elt2 -> UniqFM elt3
113 intersectsUFM :: UniqFM elt1 -> UniqFM elt2 -> Bool
115 foldUFM :: (elt -> a -> a) -> a -> UniqFM elt -> a
116 mapUFM :: (elt1 -> elt2) -> UniqFM elt1 -> UniqFM elt2
117 filterUFM :: (elt -> Bool) -> UniqFM elt -> UniqFM elt
118 filterUFM_Directly :: (Unique -> elt -> Bool) -> UniqFM elt -> UniqFM elt
120 sizeUFM :: UniqFM elt -> Int
121 hashUFM :: UniqFM elt -> Int
122 elemUFM :: Uniquable key => key -> UniqFM elt -> Bool
123 elemUFM_Directly:: Unique -> UniqFM elt -> Bool
125 lookupUFM :: Uniquable key => UniqFM elt -> key -> Maybe elt
126 lookupUFM_Directly -- when you've got the Unique already
127 :: UniqFM elt -> Unique -> Maybe elt
129 :: Uniquable key => UniqFM elt -> elt -> key -> elt
130 lookupWithDefaultUFM_Directly
131 :: UniqFM elt -> elt -> Unique -> elt
133 keysUFM :: UniqFM elt -> [Unique] -- Get the keys
134 eltsUFM :: UniqFM elt -> [elt]
135 ufmToList :: UniqFM elt -> [(Unique, elt)]
138 %************************************************************************
140 \subsection{The @IdFinMap@ and @TyVarFinMap@ specialisations for Ids/TyVars}
142 %************************************************************************
145 -- Turn off for now, these need to be updated (SDM 4/98)
148 #ifdef __GLASGOW_HASKELL__
149 -- I don't think HBC was too happy about this (WDP 94/10)
152 addListToUFM :: UniqFM elt -> [(Name, elt)] -> UniqFM elt
155 addListToUFM_C :: (elt -> elt -> elt) -> UniqFM elt -> [(Name, elt)] -> UniqFM elt
158 addToUFM :: UniqFM elt -> Unique -> elt -> UniqFM elt
161 listToUFM :: [(Unique, elt)] -> UniqFM elt
164 lookupUFM :: UniqFM elt -> Name -> Maybe elt
165 , UniqFM elt -> Unique -> Maybe elt
168 #endif /* __GLASGOW_HASKELL__ */
172 %************************************************************************
174 \subsection{Andy Gill's underlying @UniqFM@ machinery}
176 %************************************************************************
178 ``Uniq Finite maps'' are the heart and soul of the compiler's
179 lookup-tables/environments. Important stuff! It works well with
180 Dense and Sparse ranges.
181 Both @Uq@ Finite maps and @Hash@ Finite Maps
182 are built ontop of Int Finite Maps.
184 This code is explained in the paper:
186 A Gill, S Peyton Jones, B O'Sullivan, W Partain and Aqua Friends
187 "A Cheap balancing act that grows on a tree"
188 Glasgow FP Workshop, Sep 1994, pp??-??
191 %************************************************************************
193 \subsubsection{The @UniqFM@ type, and signatures for the functions}
195 %************************************************************************
197 @UniqFM a@ is a mapping from Unique to a.
199 First, the DataType itself; which is either a Node, a Leaf, or an Empty.
204 | LeafUFM FastInt ele
205 | NodeUFM FastInt -- the switching
209 -- INVARIANT: the children of a NodeUFM are never EmptyUFMs
212 -- for debugging only :-)
213 instance Outputable (UniqFM a) where
214 ppr(NodeUFM a b t1 t2) =
215 sep [text "NodeUFM " <+> int IBOX(a) <+> int IBOX(b),
216 nest 1 (parens (ppr t1)),
217 nest 1 (parens (ppr t2))]
218 ppr (LeafUFM x a) = text "LeafUFM " <+> int IBOX(x)
219 ppr (EmptyUFM) = empty
221 -- and when not debugging the package itself...
222 instance Outputable a => Outputable (UniqFM a) where
223 ppr ufm = ppr (ufmToList ufm)
226 %************************************************************************
228 \subsubsection{The @UniqFM@ functions}
230 %************************************************************************
232 First the ways of building a UniqFM.
236 unitUFM key elt = mkLeafUFM (getKey# (getUnique key)) elt
237 unitDirectlyUFM key elt = mkLeafUFM (getKey# key) elt
239 listToUFM key_elt_pairs
240 = addListToUFM_C use_snd EmptyUFM key_elt_pairs
242 listToUFM_Directly uniq_elt_pairs
243 = addListToUFM_directly_C use_snd EmptyUFM uniq_elt_pairs
246 Now ways of adding things to UniqFMs.
248 There is an alternative version of @addListToUFM_C@, that uses @plusUFM@,
249 but the semantics of this operation demands a linear insertion;
250 perhaps the version without the combinator function
251 could be optimised using it.
254 addToUFM fm key elt = addToUFM_C use_snd fm key elt
256 addToUFM_Directly fm u elt = insert_ele use_snd fm (getKey# u) elt
258 addToUFM_C combiner fm key elt
259 = insert_ele combiner fm (getKey# (getUnique key)) elt
261 addToUFM_Acc add unit fm key item
262 = insert_ele combiner fm (getKey# (getUnique key)) (unit item)
264 combiner old _unit_item = add item old
266 addListToUFM fm key_elt_pairs = addListToUFM_C use_snd fm key_elt_pairs
267 addListToUFM_Directly fm uniq_elt_pairs = addListToUFM_directly_C use_snd fm uniq_elt_pairs
269 addListToUFM_C combiner fm key_elt_pairs
270 = foldl (\ fm (k, e) -> insert_ele combiner fm (getKey# (getUnique k)) e)
273 addListToUFM_directly_C combiner fm uniq_elt_pairs
274 = foldl (\ fm (k, e) -> insert_ele combiner fm (getKey# k) e)
278 Now ways of removing things from UniqFM.
281 delListFromUFM fm lst = foldl delFromUFM fm lst
283 delFromUFM fm key = delete fm (getKey# (getUnique key))
284 delFromUFM_Directly fm u = delete fm (getKey# u)
286 delete EmptyUFM _ = EmptyUFM
287 delete fm key = del_ele fm
289 del_ele :: UniqFM a -> UniqFM a
291 del_ele lf@(LeafUFM j _)
292 | j ==# key = EmptyUFM
293 | otherwise = lf -- no delete!
295 del_ele nd@(NodeUFM j p t1 t2)
297 = mkSLNodeUFM (NodeUFMData j p) (del_ele t1) t2
299 = mkLSNodeUFM (NodeUFMData j p) t1 (del_ele t2)
301 del_ele _ = panic "Found EmptyUFM FM when rec-deleting"
304 Now ways of adding two UniqFM's together.
307 plusUFM tr1 tr2 = plusUFM_C use_snd tr1 tr2
309 plusUFM_C f EmptyUFM tr = tr
310 plusUFM_C f tr EmptyUFM = tr
311 plusUFM_C f fm1 fm2 = mix_trees fm1 fm2
313 mix_trees (LeafUFM i a) t2 = insert_ele (flip f) t2 i a
314 mix_trees t1 (LeafUFM i a) = insert_ele f t1 i a
316 mix_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
318 (ask_about_common_ancestor
322 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
326 -- t1 t2 t1' t2' j j'
331 mix_branches (NewRoot nd False)
332 = mkLLNodeUFM nd left_t right_t
333 mix_branches (NewRoot nd True)
334 = mkLLNodeUFM nd right_t left_t
340 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
342 mix_branches (SameRoot)
343 = mkSSNodeUFM (NodeUFMData j p)
346 -- Now the 4 different other ways; all like this:
348 -- Given j >^ j' (and, say, j > j')
352 -- t1 t2 t1' t2' t1 t2 + j'
355 mix_branches (LeftRoot Leftt) -- | trace "LL" True
358 (mix_trees t1 right_t)
361 mix_branches (LeftRoot Rightt) -- | trace "LR" True
365 (mix_trees t2 right_t)
367 mix_branches (RightRoot Leftt) -- | trace "RL" True
370 (mix_trees left_t t1')
373 mix_branches (RightRoot Rightt) -- | trace "RR" True
377 (mix_trees left_t t2')
379 mix_trees _ _ = panic "EmptyUFM found when inserting into plusInt"
382 And ways of subtracting them. First the base cases,
383 then the full D&C approach.
386 minusUFM EmptyUFM _ = EmptyUFM
387 minusUFM t1 EmptyUFM = t1
388 minusUFM fm1 fm2 = minus_trees fm1 fm2
391 -- Notice the asymetry of subtraction
393 minus_trees lf@(LeafUFM i a) t2 =
398 minus_trees t1 (LeafUFM i _) = delete t1 i
400 minus_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
402 (ask_about_common_ancestor
406 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
410 -- t1 t2 t1' t2' t1 t2
415 minus_branches (NewRoot nd _) = left_t
421 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
423 minus_branches (SameRoot)
424 = mkSSNodeUFM (NodeUFMData j p)
427 -- Now the 4 different other ways; all like this:
428 -- again, with asymatry
431 -- The left is above the right
433 minus_branches (LeftRoot Leftt)
436 (minus_trees t1 right_t)
438 minus_branches (LeftRoot Rightt)
442 (minus_trees t2 right_t)
445 -- The right is above the left
447 minus_branches (RightRoot Leftt)
448 = minus_trees left_t t1'
449 minus_branches (RightRoot Rightt)
450 = minus_trees left_t t2'
452 minus_trees _ _ = panic "EmptyUFM found when insering into plusInt"
455 And taking the intersection of two UniqFM's.
458 intersectUFM t1 t2 = intersectUFM_C use_snd t1 t2
459 intersectsUFM t1 t2 = isNullUFM (intersectUFM_C (\ _ _ -> error "urk") t1 t2)
461 intersectUFM_C f EmptyUFM _ = EmptyUFM
462 intersectUFM_C f _ EmptyUFM = EmptyUFM
463 intersectUFM_C f fm1 fm2 = intersect_trees fm1 fm2
465 intersect_trees (LeafUFM i a) t2 =
468 Just b -> mkLeafUFM i (f a b)
470 intersect_trees t1 (LeafUFM i a) =
473 Just b -> mkLeafUFM i (f b a)
475 intersect_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
477 (ask_about_common_ancestor
481 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
484 -- / \ + / \ ==> EmptyUFM
489 intersect_branches (NewRoot nd _) = EmptyUFM
495 -- t1 t2 t1' t2' t1 x t1' t2 x t2'
497 intersect_branches (SameRoot)
498 = mkSSNodeUFM (NodeUFMData j p)
499 (intersect_trees t1 t1')
500 (intersect_trees t2 t2')
501 -- Now the 4 different other ways; all like this:
503 -- Given j >^ j' (and, say, j > j')
507 -- t1 t2 t1' t2' t1' t2'
509 -- This does cut down the search space quite a bit.
511 intersect_branches (LeftRoot Leftt)
512 = intersect_trees t1 right_t
513 intersect_branches (LeftRoot Rightt)
514 = intersect_trees t2 right_t
515 intersect_branches (RightRoot Leftt)
516 = intersect_trees left_t t1'
517 intersect_branches (RightRoot Rightt)
518 = intersect_trees left_t t2'
520 intersect_trees x y = panic ("EmptyUFM found when intersecting trees")
523 Now the usual set of `collection' operators, like map, fold, etc.
526 foldUFM f a (NodeUFM _ _ t1 t2) = foldUFM f (foldUFM f a t2) t1
527 foldUFM f a (LeafUFM _ obj) = f obj a
528 foldUFM f a EmptyUFM = a
532 mapUFM fn EmptyUFM = EmptyUFM
533 mapUFM fn fm = map_tree fn fm
535 filterUFM fn EmptyUFM = EmptyUFM
536 filterUFM fn fm = filter_tree pred fm
538 pred (i::FastInt) e = fn e
540 filterUFM_Directly fn EmptyUFM = EmptyUFM
541 filterUFM_Directly fn fm = filter_tree pred fm
543 pred i e = fn (mkUniqueGrimily (iBox i)) e
546 Note, this takes a long time, O(n), but
547 because we dont want to do this very often, we put up with this.
548 O'rable, but how often do we look at the size of
553 sizeUFM (NodeUFM _ _ t1 t2) = sizeUFM t1 + sizeUFM t2
554 sizeUFM (LeafUFM _ _) = 1
556 isNullUFM EmptyUFM = True
559 -- hashing is used in VarSet.uniqAway, and should be fast
560 -- We use a cheap and cheerful method for now
562 hashUFM (NodeUFM n _ _ _) = iBox n
563 hashUFM (LeafUFM n _) = iBox n
566 looking up in a hurry is the {\em whole point} of this binary tree lark.
567 Lookup up a binary tree is easy (and fast).
570 elemUFM key fm = maybeToBool (lookupUFM fm key)
571 elemUFM_Directly key fm = maybeToBool (lookupUFM_Directly fm key)
573 lookupUFM fm key = lookUp fm (getKey# (getUnique key))
574 lookupUFM_Directly fm key = lookUp fm (getKey# key)
576 lookupWithDefaultUFM fm deflt key
577 = case lookUp fm (getKey# (getUnique key)) of
581 lookupWithDefaultUFM_Directly fm deflt key
582 = case lookUp fm (getKey# key) of
586 lookUp EmptyUFM _ = Nothing
587 lookUp fm i = lookup_tree fm
589 lookup_tree :: UniqFM a -> Maybe a
591 lookup_tree (LeafUFM j b)
593 | otherwise = Nothing
594 lookup_tree (NodeUFM j p t1 t2)
595 | j ># i = lookup_tree t1
596 | otherwise = lookup_tree t2
598 lookup_tree EmptyUFM = panic "lookup Failed"
601 folds are *wonderful* things.
604 eltsUFM fm = foldUFM (:) [] fm
606 ufmToList fm = fold_tree (\ iu elt rest -> (mkUniqueGrimily (iBox iu), elt) : rest) [] fm
608 keysUFM fm = fold_tree (\ iu elt rest -> mkUniqueGrimily (iBox iu) : rest) [] fm
610 fold_tree f a (NodeUFM _ _ t1 t2) = fold_tree f (fold_tree f a t2) t1
611 fold_tree f a (LeafUFM iu obj) = f iu obj a
612 fold_tree f a EmptyUFM = a
615 %************************************************************************
617 \subsubsection{The @UniqFM@ type, and its functions}
619 %************************************************************************
621 You should always use these to build the tree.
622 There are 4 versions of mkNodeUFM, depending on
623 the strictness of the two sub-tree arguments.
624 The strictness is used *both* to prune out
625 empty trees, *and* to improve performance,
626 stoping needless thunks lying around.
627 The rule of thumb (from experence with these trees)
628 is make thunks strict, but data structures lazy.
629 If in doubt, use mkSSNodeUFM, which has the `strongest'
630 functionality, but may do a few needless evaluations.
633 mkLeafUFM :: FastInt -> a -> UniqFM a
634 mkLeafUFM i a = LeafUFM i a
636 -- The *ONLY* ways of building a NodeUFM.
638 mkSSNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
639 mkSSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
640 mkSSNodeUFM (NodeUFMData j p) t1 t2
641 = ASSERT(correctNodeUFM (iBox j) (iBox p) t1 t2)
644 mkSLNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
645 mkSLNodeUFM (NodeUFMData j p) t1 t2
646 = ASSERT(correctNodeUFM (iBox j) (iBox p) t1 t2)
649 mkLSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
650 mkLSNodeUFM (NodeUFMData j p) t1 t2
651 = ASSERT(correctNodeUFM (iBox j) (iBox p) t1 t2)
654 mkLLNodeUFM (NodeUFMData j p) t1 t2
655 = ASSERT(correctNodeUFM (iBox j) (iBox p) t1 t2)
665 correctNodeUFM j p t1 t2
666 = correct (j-p) (j-1) p t1 && correct j ((j-1)+p) p t2
668 correct low high _ (LeafUFM i _)
669 = low <= iBox i && iBox i <= high
670 correct low high above_p (NodeUFM j p _ _)
671 = low <= iBox j && iBox j <= high && above_p > iBox p
672 correct _ _ _ EmptyUFM = panic "EmptyUFM stored inside a tree"
675 Note: doing SAT on this by hand seems to make it worse. Todo: Investigate,
676 and if necessary do $\lambda$ lifting on our functions that are bound.
680 :: (a -> a -> a) -- old -> new -> result
686 insert_ele f EmptyUFM i new = mkLeafUFM i new
688 insert_ele f (LeafUFM j old) i new
690 mkLLNodeUFM (getCommonNodeUFMData
695 | j ==# i = mkLeafUFM j (f old new)
697 mkLLNodeUFM (getCommonNodeUFMData
703 insert_ele f n@(NodeUFM j p t1 t2) i a
705 = if (i >=# (j -# p))
706 then mkSLNodeUFM (NodeUFMData j p) (insert_ele f t1 i a) t2
707 else mkLLNodeUFM (getCommonNodeUFMData
713 = if (i <=# ((j -# _ILIT(1)) +# p))
714 then mkLSNodeUFM (NodeUFMData j p) t1 (insert_ele f t2 i a)
715 else mkLLNodeUFM (getCommonNodeUFMData
725 map_tree f (NodeUFM j p t1 t2)
726 = mkLLNodeUFM (NodeUFMData j p) (map_tree f t1) (map_tree f t2)
727 -- NB. lazy! we know the tree is well-formed.
728 map_tree f (LeafUFM i obj)
729 = mkLeafUFM i (f obj)
730 map_tree f _ = panic "map_tree failed"
734 filter_tree :: (FastInt -> a -> Bool) -> UniqFM a -> UniqFM a
735 filter_tree f nd@(NodeUFM j p t1 t2)
736 = mkSSNodeUFM (NodeUFMData j p) (filter_tree f t1) (filter_tree f t2)
738 filter_tree f lf@(LeafUFM i obj)
740 | otherwise = EmptyUFM
741 filter_tree f _ = panic "filter_tree failed"
744 %************************************************************************
746 \subsubsection{The @UniqFM@ type, and signatures for the functions}
748 %************************************************************************
752 This is the information that is held inside a NodeUFM, packaged up for
757 = NodeUFMData FastInt
761 This is the information used when computing new NodeUFMs.
764 data Side = Leftt | Rightt -- NB: avoid 1.3 names "Left" and "Right"
766 = LeftRoot Side -- which side is the right down ?
767 | RightRoot Side -- which side is the left down ?
768 | SameRoot -- they are the same !
769 | NewRoot NodeUFMData -- here's the new, common, root
770 Bool -- do you need to swap left and right ?
773 This specifies the relationship between NodeUFMData and CalcNodeUFMData.
776 indexToRoot :: FastInt -> NodeUFMData
780 l = (_ILIT(1) :: FastInt)
782 NodeUFMData (((i `shiftR_` l) `shiftL_` l) +# _ILIT(1)) l
784 getCommonNodeUFMData :: NodeUFMData -> NodeUFMData -> NodeUFMData
786 getCommonNodeUFMData (NodeUFMData i p) (NodeUFMData i2 p2)
787 | p ==# p2 = getCommonNodeUFMData_ p j j2
788 | p <# p2 = getCommonNodeUFMData_ p2 (j `quotFastInt` (p2 `quotFastInt` p)) j2
789 | otherwise = getCommonNodeUFMData_ p j (j2 `quotFastInt` (p `quotFastInt` p2))
791 l = (_ILIT(1) :: FastInt)
792 j = i `quotFastInt` (p `shiftL_` l)
793 j2 = i2 `quotFastInt` (p2 `shiftL_` l)
795 getCommonNodeUFMData_ :: FastInt -> FastInt -> FastInt -> NodeUFMData
797 getCommonNodeUFMData_ p j j_
799 = NodeUFMData (((j `shiftL_` l) +# l) *# p) p
801 = getCommonNodeUFMData_ (p `shiftL_` l) (j `shiftR_` l) (j_ `shiftR_` l)
803 ask_about_common_ancestor :: NodeUFMData -> NodeUFMData -> CommonRoot
805 ask_about_common_ancestor x@(NodeUFMData j p) y@(NodeUFMData j2 p2)
806 | j ==# j2 = SameRoot
808 = case getCommonNodeUFMData x y of
809 nd@(NodeUFMData j3 p3)
810 | j3 ==# j -> LeftRoot (decideSide (j ># j2))
811 | j3 ==# j2 -> RightRoot (decideSide (j <# j2))
812 | otherwise -> NewRoot nd (j ># j2)
814 decideSide :: Bool -> Side
815 decideSide True = Leftt
816 decideSide False = Rightt
819 This might be better in Util.lhs ?
822 Now the bit twiddling functions.
824 shiftL_ :: FastInt -> FastInt -> FastInt
825 shiftR_ :: FastInt -> FastInt -> FastInt
827 #if __GLASGOW_HASKELL__
828 {-# INLINE shiftL_ #-}
829 {-# INLINE shiftR_ #-}
830 #if __GLASGOW_HASKELL__ >= 503
831 shiftL_ n p = word2Int#((int2Word# n) `uncheckedShiftL#` p)
833 shiftL_ n p = word2Int#((int2Word# n) `shiftL#` p)
835 shiftR_ n p = word2Int#((int2Word# n) `shiftr` p)
837 #if __GLASGOW_HASKELL__ >= 503
838 shiftr x y = uncheckedShiftRL# x y
840 shiftr x y = shiftRL# x y
844 shiftL_ n p = n * (2 ^ p)
845 shiftR_ n p = n `quot` (2 ^ p)
851 use_snd :: a -> b -> b