[project @ 1998-04-16 09:08:32 by simonm]
[ghc-hetmet.git] / ghc / compiler / utils / UniqFM.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1994-1996
3 %
4 \section[UniqFM]{Specialised finite maps, for things with @Uniques@}
5
6 Based on @FiniteMaps@ (as you would expect).
7
8 Basically, the things need to be in class @Uniquable@, and we use the
9 @uniqueOf@ method to grab their @Uniques@.
10
11 (A similar thing to @UniqSet@, as opposed to @Set@.)
12
13 \begin{code}
14 module UniqFM (
15         UniqFM,   -- abstract type
16
17         emptyUFM,
18         unitUFM,
19         unitDirectlyUFM,
20         listToUFM,
21         listToUFM_Directly,
22         addToUFM,addToUFM_C,
23         addListToUFM,addListToUFM_C,
24         addToUFM_Directly,
25         addListToUFM_Directly,
26         delFromUFM,
27         delFromUFM_Directly,
28         delListFromUFM,
29         plusUFM,
30         plusUFM_C,
31         minusUFM,
32         intersectUFM,
33         intersectUFM_C,
34         foldUFM,
35         mapUFM,
36         elemUFM,
37         filterUFM,
38         sizeUFM,
39         isNullUFM,
40         lookupUFM, lookupUFM_Directly,
41         lookupWithDefaultUFM, lookupWithDefaultUFM_Directly,
42         eltsUFM, keysUFM,
43         ufmToList, 
44         FastString
45     ) where
46
47 #include "HsVersions.h"
48
49 import {-# SOURCE #-} Name      ( Name )
50
51 import Unique           ( Uniquable(..), Unique, u2i, mkUniqueGrimily )
52 import Util
53 import GlaExts          -- Lots of Int# operations
54
55 #if ! OMIT_NATIVE_CODEGEN
56 #define IF_NCG(a) a
57 #else
58 #define IF_NCG(a) {--}
59 #endif
60 \end{code}
61
62 %************************************************************************
63 %*                                                                      *
64 \subsection{The @UniqFM@ type, and signatures for the functions}
65 %*                                                                      *
66 %************************************************************************
67
68 We use @FiniteMaps@, with a (@uniqueOf@-able) @Unique@ as ``key''.
69
70 \begin{code}
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
77 listToUFM_Directly
78                 :: [(Unique, elt)] -> UniqFM elt
79
80 addToUFM        :: Uniquable key => UniqFM elt -> key -> elt  -> UniqFM elt
81 addListToUFM    :: Uniquable key => UniqFM elt -> [(key,elt)] -> UniqFM elt
82 addToUFM_Directly
83                 :: UniqFM elt -> Unique -> elt -> UniqFM elt
84
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)]
89                            -> UniqFM elt
90
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
94
95 plusUFM         :: UniqFM elt -> UniqFM elt -> UniqFM elt
96
97 plusUFM_C       :: (elt -> elt -> elt)
98                 -> UniqFM elt -> UniqFM elt -> UniqFM elt
99
100 minusUFM        :: UniqFM elt -> UniqFM elt -> UniqFM elt
101
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
108
109 sizeUFM         :: UniqFM elt -> Int
110 elemUFM         :: Uniquable key => key -> UniqFM elt -> Bool
111
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
115 lookupWithDefaultUFM
116                 :: Uniquable key => UniqFM elt -> elt -> key -> elt
117 lookupWithDefaultUFM_Directly
118                 :: UniqFM elt -> elt -> Unique -> elt
119
120 keysUFM         :: UniqFM elt -> [Int]          -- Get the keys
121 eltsUFM         :: UniqFM elt -> [elt]
122 ufmToList       :: UniqFM elt -> [(Unique, elt)]
123 \end{code}
124
125 %************************************************************************
126 %*                                                                      *
127 \subsection{The @IdFinMap@ and @TyVarFinMap@ specialisations for Ids/TyVars}
128 %*                                                                      *
129 %************************************************************************
130
131 \begin{code}
132 -- Turn off for now, these need to be updated (SDM 4/98)
133
134 #if 0
135 #ifdef __GLASGOW_HASKELL__
136 -- I don't think HBC was too happy about this (WDP 94/10)
137
138 {-# SPECIALIZE
139     addListToUFM :: UniqFM elt -> [(Name,   elt)] -> UniqFM elt
140   #-}
141 {-# SPECIALIZE
142     addListToUFM_C :: (elt -> elt -> elt) -> UniqFM elt -> [(Name,  elt)] -> UniqFM elt
143   #-}
144 {-# SPECIALIZE
145     addToUFM    :: UniqFM elt -> Unique -> elt  -> UniqFM elt
146   #-}
147 {-# SPECIALIZE
148     listToUFM   :: [(Unique, elt)]     -> UniqFM elt
149   #-}
150 {-# SPECIALIZE
151     lookupUFM   :: UniqFM elt -> Name   -> Maybe elt
152                  , UniqFM elt -> Unique -> Maybe elt
153   #-}
154
155 #endif {- __GLASGOW_HASKELL__ -}
156 #endif
157 \end{code}
158
159 %************************************************************************
160 %*                                                                      *
161 \subsection{Andy Gill's underlying @UniqFM@ machinery}
162 %*                                                                      *
163 %************************************************************************
164
165 ``Uniq Finite maps'' are the heart and soul of the compiler's
166 lookup-tables/environments.  Important stuff!  It works well with
167 Dense and Sparse ranges.
168 Both @Uq@ Finite maps and @Hash@ Finite Maps
169 are built ontop of Int Finite Maps.
170
171 This code is explained in the paper:
172 \begin{display}
173         A Gill, S Peyton Jones, B O'Sullivan, W Partain and Aqua Friends
174         "A Cheap balancing act that grows on a tree"
175         Glasgow FP Workshop, Sep 1994, pp??-??
176 \end{display}
177
178 %************************************************************************
179 %*                                                                      *
180 \subsubsection{The @UniqFM@ type, and signatures for the functions}
181 %*                                                                      *
182 %************************************************************************
183
184 @UniqFM a@ is a mapping from Unique to a.
185
186 First, the DataType itself; which is either a Node, a Leaf, or an Empty.
187
188 \begin{code}
189 data UniqFM ele
190   = EmptyUFM
191   | LeafUFM FAST_INT ele
192   | NodeUFM FAST_INT        -- the switching
193             FAST_INT        -- the delta
194             (UniqFM ele)
195             (UniqFM ele)
196
197 -- for debugging only :-)
198 {-
199 instance Text (UniqFM a) where
200         showsPrec _ (NodeUFM a b t1 t2) =
201                   showString "NodeUFM " . shows (IBOX(a))
202                 . showString " " . shows (IBOX(b))
203                 . showString " (" . shows t1
204                 . showString ") (" . shows t2
205                 . showString ")"
206         showsPrec _ (LeafUFM x a) = showString "LeafUFM " . shows (IBOX(x))
207         showsPrec _ (EmptyUFM) = id
208 -}
209 \end{code}
210
211 %************************************************************************
212 %*                                                                      *
213 \subsubsection{The @UniqFM@ functions}
214 %*                                                                      *
215 %************************************************************************
216
217 First the ways of building a UniqFM.
218
219 \begin{code}
220 emptyUFM                     = EmptyUFM
221 unitUFM      key elt = mkLeafUFM (u2i (uniqueOf key)) elt
222 unitDirectlyUFM key elt = mkLeafUFM (u2i key) elt
223
224 listToUFM key_elt_pairs
225   = addListToUFM_C use_snd EmptyUFM key_elt_pairs
226
227 listToUFM_Directly uniq_elt_pairs
228   = addListToUFM_directly_C use_snd EmptyUFM uniq_elt_pairs
229 \end{code}
230
231 Now ways of adding things to UniqFMs.
232
233 There is an alternative version of @addListToUFM_C@, that uses @plusUFM@,
234 but the semantics of this operation demands a linear insertion;
235 perhaps the version without the combinator function
236 could be optimised using it.
237
238 \begin{code}
239 addToUFM fm key elt = addToUFM_C use_snd fm key elt
240
241 addToUFM_Directly fm u elt = insert_ele use_snd fm (u2i u) elt
242
243 addToUFM_C combiner fm key elt
244   = insert_ele combiner fm (u2i (uniqueOf key)) elt
245
246 addListToUFM fm key_elt_pairs = addListToUFM_C use_snd fm key_elt_pairs
247 addListToUFM_Directly fm uniq_elt_pairs = addListToUFM_directly_C use_snd fm uniq_elt_pairs
248
249 addListToUFM_C combiner fm key_elt_pairs
250  = foldl (\ fm (k, e) -> insert_ele combiner fm (u2i (uniqueOf k)) e)
251          fm key_elt_pairs
252
253 addListToUFM_directly_C combiner fm uniq_elt_pairs
254  = foldl (\ fm (k, e) -> insert_ele combiner fm (u2i k) e)
255          fm uniq_elt_pairs
256 \end{code}
257
258 Now ways of removing things from UniqFM.
259
260 \begin{code}
261 delListFromUFM fm lst = foldl delFromUFM fm lst
262
263 delFromUFM          fm key = delete fm (u2i (uniqueOf key))
264 delFromUFM_Directly fm u   = delete fm (u2i u)
265
266 delete EmptyUFM _   = EmptyUFM
267 delete fm       key = del_ele fm
268   where
269     del_ele :: UniqFM a -> UniqFM a
270
271     del_ele lf@(LeafUFM j _)
272       | j _EQ_ key      = EmptyUFM
273       | otherwise       = lf    -- no delete!
274
275     del_ele nd@(NodeUFM j p t1 t2)
276       | j _GT_ key
277       = mkSLNodeUFM (NodeUFMData j p) (del_ele t1) t2
278       | otherwise
279       = mkLSNodeUFM (NodeUFMData j p) t1 (del_ele t2)
280
281     del_ele _ = panic "Found EmptyUFM FM when rec-deleting"
282 \end{code}
283
284 Now ways of adding two UniqFM's together.
285
286 \begin{code}
287 plusUFM tr1 tr2 = plusUFM_C use_snd tr1 tr2
288
289 plusUFM_C f EmptyUFM tr = tr
290 plusUFM_C f tr EmptyUFM = tr
291 plusUFM_C f fm1 fm2     = mix_trees fm1 fm2
292     where
293         mix_trees (LeafUFM i a) t2 = insert_ele (flip f) t2 i a
294         mix_trees t1 (LeafUFM i a) = insert_ele f        t1 i a
295
296         mix_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
297           = mix_branches
298                 (ask_about_common_ancestor
299                         (NodeUFMData j p)
300                         (NodeUFMData j' p'))
301           where
302                 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
303                 --
304                 --        j             j'                      (C j j')
305                 --       / \    +      / \      ==>             /       \
306                 --     t1   t2      t1'   t2'                  j         j'
307                 --                                            / \       / \
308                 --                                           t1  t2   t1'  t2'
309                 -- Fast, Ehh !
310                 --
311           mix_branches (NewRoot nd False)
312                 = mkLLNodeUFM nd left_t right_t
313           mix_branches (NewRoot nd True)
314                 = mkLLNodeUFM nd right_t left_t
315
316                 -- Now, if j == j':
317                 --
318                 --        j             j'                       j
319                 --       / \    +      / \      ==>             / \
320                 --     t1   t2      t1'   t2'           t1 + t1'   t2 + t2'
321                 --
322           mix_branches (SameRoot)
323                 = mkSSNodeUFM (NodeUFMData j p)
324                         (mix_trees t1 t1')
325                         (mix_trees t2 t2')
326                 -- Now the 4 different other ways; all like this:
327                 --
328                 -- Given j >^ j' (and, say,  j > j')
329                 --
330                 --        j             j'                       j
331                 --       / \    +      / \      ==>             / \
332                 --     t1   t2      t1'   t2'                 t1   t2 + j'
333                 --                                                     / \
334                 --                                                   t1'  t2'
335           mix_branches (LeftRoot Leftt) -- | trace "LL" True
336             = mkSLNodeUFM
337                 (NodeUFMData j p)
338                 (mix_trees t1 right_t)
339                 t2
340
341           mix_branches (LeftRoot Rightt) -- | trace "LR" True
342             = mkLSNodeUFM
343                 (NodeUFMData j p)
344                 t1
345                 (mix_trees t2 right_t)
346
347           mix_branches (RightRoot Leftt) -- | trace "RL" True
348             = mkSLNodeUFM
349                 (NodeUFMData j' p')
350                 (mix_trees left_t t1')
351                 t2'
352
353           mix_branches (RightRoot Rightt) -- | trace "RR" True
354             = mkLSNodeUFM
355                 (NodeUFMData j' p')
356                 t1'
357                 (mix_trees left_t t2')
358
359         mix_trees _ _ = panic "EmptyUFM found when inserting into plusInt"
360 \end{code}
361
362 And ways of subtracting them. First the base cases,
363 then the full D&C approach.
364
365 \begin{code}
366 minusUFM EmptyUFM _  = EmptyUFM
367 minusUFM t1 EmptyUFM = t1
368 minusUFM fm1 fm2     = minus_trees fm1 fm2
369     where
370         --
371         -- Notice the asymetry of subtraction
372         --
373         minus_trees lf@(LeafUFM i a) t2 =
374                 case lookUp t2 i of
375                   Nothing -> lf
376                   Just b -> EmptyUFM
377
378         minus_trees t1 (LeafUFM i _) = delete t1 i
379
380         minus_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
381           = minus_branches
382                 (ask_about_common_ancestor
383                         (NodeUFMData j p)
384                         (NodeUFMData j' p'))
385           where
386                 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
387                 --
388                 --        j             j'                 j
389                 --       / \    +      / \      ==>       / \
390                 --     t1   t2      t1'   t2'            t1  t2
391                 --
392                 --
393                 -- Fast, Ehh !
394                 --
395           minus_branches (NewRoot nd _) = left_t
396
397                 -- Now, if j == j':
398                 --
399                 --        j             j'                       j
400                 --       / \    +      / \      ==>             / \
401                 --     t1   t2      t1'   t2'           t1 + t1'   t2 + t2'
402                 --
403           minus_branches (SameRoot)
404                 = mkSSNodeUFM (NodeUFMData j p)
405                         (minus_trees t1 t1')
406                         (minus_trees t2 t2')
407                 -- Now the 4 different other ways; all like this:
408                 -- again, with asymatry
409
410                 --
411                 -- The left is above the right
412                 --
413           minus_branches (LeftRoot Leftt)
414             = mkSLNodeUFM
415                 (NodeUFMData j p)
416                 (minus_trees t1 right_t)
417                 t2
418           minus_branches (LeftRoot Rightt)
419             = mkLSNodeUFM
420                 (NodeUFMData j p)
421                 t1
422                 (minus_trees t2 right_t)
423
424                 --
425                 -- The right is above the left
426                 --
427           minus_branches (RightRoot Leftt)
428             = minus_trees left_t t1'
429           minus_branches (RightRoot Rightt)
430             = minus_trees left_t t2'
431
432         minus_trees _ _ = panic "EmptyUFM found when insering into plusInt"
433 \end{code}
434
435 And taking the intersection of two UniqFM's.
436
437 \begin{code}
438 intersectUFM t1 t2 = intersectUFM_C use_snd t1 t2
439
440 intersectUFM_C f EmptyUFM _ = EmptyUFM
441 intersectUFM_C f _ EmptyUFM = EmptyUFM
442 intersectUFM_C f fm1 fm2    = intersect_trees fm1 fm2
443     where
444         intersect_trees (LeafUFM i a) t2 =
445                 case lookUp t2 i of
446                   Nothing -> EmptyUFM
447                   Just b -> mkLeafUFM i (f a b)
448
449         intersect_trees t1 (LeafUFM i a) =
450                 case lookUp t1 i of
451                   Nothing -> EmptyUFM
452                   Just b -> mkLeafUFM i (f b a)
453
454         intersect_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
455           = intersect_branches
456                 (ask_about_common_ancestor
457                         (NodeUFMData j p)
458                         (NodeUFMData j' p'))
459           where
460                 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
461                 --
462                 --        j             j'
463                 --       / \    +      / \      ==>             EmptyUFM
464                 --     t1   t2      t1'   t2'
465                 --
466                 -- Fast, Ehh !
467                 --
468           intersect_branches (NewRoot nd _) = EmptyUFM
469
470                 -- Now, if j == j':
471                 --
472                 --        j             j'                       j
473                 --       / \    +      / \      ==>             / \
474                 --     t1   t2      t1'   t2'           t1 x t1'   t2 x t2'
475                 --
476           intersect_branches (SameRoot)
477                 = mkSSNodeUFM (NodeUFMData j p)
478                         (intersect_trees t1 t1')
479                         (intersect_trees t2 t2')
480                 -- Now the 4 different other ways; all like this:
481                 --
482                 -- Given j >^ j' (and, say,  j > j')
483                 --
484                 --        j             j'                     t2 + j'
485                 --       / \    +      / \      ==>                / \
486                 --     t1   t2      t1'   t2'                    t1'  t2'
487                 --
488                 -- This does cut down the search space quite a bit.
489
490           intersect_branches (LeftRoot Leftt)
491             = intersect_trees t1 right_t
492           intersect_branches (LeftRoot Rightt)
493             = intersect_trees t2 right_t
494           intersect_branches (RightRoot Leftt)
495             = intersect_trees left_t t1'
496           intersect_branches (RightRoot Rightt)
497             = intersect_trees left_t t2'
498
499         intersect_trees x y = panic ("EmptyUFM found when intersecting trees")
500 \end{code}
501
502 Now the usual set of `collection' operators, like map, fold, etc.
503
504 \begin{code}
505 foldUFM f a (NodeUFM _ _ t1 t2) = foldUFM f (foldUFM f a t2) t1
506 foldUFM f a (LeafUFM _ obj)     = f obj a
507 foldUFM f a EmptyUFM            = a
508 \end{code}
509
510 \begin{code}
511 mapUFM fn EmptyUFM    = EmptyUFM
512 mapUFM fn fm          = map_tree fn fm
513
514 filterUFM fn EmptyUFM = EmptyUFM
515 filterUFM fn fm       = filter_tree fn fm
516 \end{code}
517
518 Note, this takes a long time, O(n), but
519 because we dont want to do this very often, we put up with this.
520 O'rable, but how often do we look at the size of
521 a finite map?
522
523 \begin{code}
524 sizeUFM EmptyUFM            = 0
525 sizeUFM (NodeUFM _ _ t1 t2) = sizeUFM t1 + sizeUFM t2
526 sizeUFM (LeafUFM _ _)       = 1
527
528 isNullUFM EmptyUFM = True
529 isNullUFM _        = False
530 \end{code}
531
532 looking up in a hurry is the {\em whole point} of this binary tree lark.
533 Lookup up a binary tree is easy (and fast).
534
535 \begin{code}
536 elemUFM key fm = case lookUp fm (u2i (uniqueOf key)) of
537                         Nothing -> False
538                         Just _  -> True
539
540 lookupUFM          fm key = lookUp fm (u2i (uniqueOf key))
541 lookupUFM_Directly fm key = lookUp fm (u2i key)
542
543 lookupWithDefaultUFM fm deflt key
544   = case lookUp fm (u2i (uniqueOf key)) of
545       Nothing  -> deflt
546       Just elt -> elt
547
548 lookupWithDefaultUFM_Directly fm deflt key
549   = case lookUp fm (u2i key) of
550       Nothing  -> deflt
551       Just elt -> elt
552
553 lookUp EmptyUFM _   = Nothing
554 lookUp fm i         = lookup_tree fm
555   where
556         lookup_tree :: UniqFM a -> Maybe a
557
558         lookup_tree (LeafUFM j b)
559           | j _EQ_ i    = Just b
560           | otherwise   = Nothing
561         lookup_tree (NodeUFM j p t1 t2)
562           | j _GT_ i    = lookup_tree t1
563           | otherwise   = lookup_tree t2
564
565         lookup_tree EmptyUFM = panic "lookup Failed"
566 \end{code}
567
568 folds are *wonderful* things.
569
570 \begin{code}
571 eltsUFM fm = foldUFM (:) [] fm
572
573 ufmToList fm = fold_tree (\ iu elt rest -> (mkUniqueGrimily iu, elt) : rest) [] fm
574
575 keysUFM fm = fold_tree (\ iu elt rest -> IBOX(iu) : rest) [] fm
576
577 fold_tree f a (NodeUFM _ _ t1 t2) = fold_tree f (fold_tree f a t2) t1
578 fold_tree f a (LeafUFM iu obj)    = f iu obj a
579 fold_tree f a EmptyUFM            = a
580 \end{code}
581
582 %************************************************************************
583 %*                                                                      *
584 \subsubsection{The @UniqFM@ type, and its functions}
585 %*                                                                      *
586 %************************************************************************
587
588 You should always use these to build the tree.
589 There are 4 versions of mkNodeUFM, depending on
590 the strictness of the two sub-tree arguments.
591 The strictness is used *both* to prune out
592 empty trees, *and* to improve performance,
593 stoping needless thunks lying around.
594 The rule of thumb (from experence with these trees)
595 is make thunks strict, but data structures lazy.
596 If in doubt, use mkSSNodeUFM, which has the `strongest'
597 functionality, but may do a few needless evaluations.
598
599 \begin{code}
600 mkLeafUFM :: FAST_INT -> a -> UniqFM a
601 mkLeafUFM i a     = LeafUFM i a
602
603 -- The *ONLY* ways of building a NodeUFM.
604
605 mkSSNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
606 mkSSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
607 mkSSNodeUFM (NodeUFMData j p) t1 t2
608   = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
609     NodeUFM j p t1 t2
610
611 mkSLNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
612 mkSLNodeUFM (NodeUFMData j p) t1 t2
613   = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
614     NodeUFM j p t1 t2
615
616 mkLSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
617 mkLSNodeUFM (NodeUFMData j p) t1 t2
618   = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
619     NodeUFM j p t1 t2
620
621 mkLLNodeUFM (NodeUFMData j p) t1 t2
622   = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
623     NodeUFM j p t1 t2
624
625 correctNodeUFM
626         :: Int
627         -> Int
628         -> UniqFM a
629         -> UniqFM a
630         -> Bool
631
632 correctNodeUFM j p t1 t2
633   = correct (j-p) (j-1) p t1 && correct j ((j-1)+p) p t2
634   where
635     correct low high _ (LeafUFM i _)
636       = low <= IBOX(i) && IBOX(i) <= high
637     correct low high above_p (NodeUFM j p _ _)
638       = low <= IBOX(j) && IBOX(j) <= high && above_p > IBOX(p)
639     correct _ _ _ EmptyUFM = panic "EmptyUFM stored inside a tree"
640 \end{code}
641
642 Note: doing SAT on this by hand seems to make it worse. Todo: Investigate,
643 and if necessary do $\lambda$ lifting on our functions that are bound.
644
645 \begin{code}
646 insert_ele
647         :: (a -> a -> a)
648         -> UniqFM a
649         -> FAST_INT
650         -> a
651         -> UniqFM a
652
653 insert_ele f EmptyUFM i new = mkLeafUFM i new
654
655 insert_ele f (LeafUFM j old) i new
656   | j _GT_ i =
657           mkLLNodeUFM (getCommonNodeUFMData
658                           (indexToRoot i)
659                           (indexToRoot j))
660                  (mkLeafUFM i new)
661                  (mkLeafUFM j old)
662   | j _EQ_ i  = mkLeafUFM j (f old new)
663   | otherwise =
664           mkLLNodeUFM (getCommonNodeUFMData
665                           (indexToRoot i)
666                           (indexToRoot j))
667                  (mkLeafUFM j old)
668                  (mkLeafUFM i new)
669
670 insert_ele f n@(NodeUFM j p t1 t2) i a
671   | i _LT_ j
672     = if (i _GE_ (j _SUB_ p))
673       then mkSLNodeUFM (NodeUFMData j p) (insert_ele f t1 i a) t2
674       else mkLLNodeUFM (getCommonNodeUFMData
675                           (indexToRoot i)
676                           ((NodeUFMData j p)))
677                   (mkLeafUFM i a)
678                   n
679   | otherwise
680     = if (i _LE_ ((j _SUB_ ILIT(1)) _ADD_ p))
681       then mkLSNodeUFM (NodeUFMData j p) t1 (insert_ele f t2 i a)
682       else mkLLNodeUFM (getCommonNodeUFMData
683                           (indexToRoot i)
684                           ((NodeUFMData j p)))
685                   n
686                   (mkLeafUFM i a)
687 \end{code}
688
689
690
691 \begin{code}
692 map_tree f (NodeUFM j p t1 t2)
693   = mkSSNodeUFM (NodeUFMData j p) (map_tree f t1) (map_tree f t2)
694 map_tree f (LeafUFM i obj)
695   = mkLeafUFM i (f obj)
696
697 map_tree f _ = panic "map_tree failed"
698 \end{code}
699
700 \begin{code}
701 filter_tree f nd@(NodeUFM j p t1 t2)
702   = mkSSNodeUFM (NodeUFMData j p) (filter_tree f t1) (filter_tree f t2)
703
704 filter_tree f lf@(LeafUFM i obj)
705   | f obj = lf
706   | otherwise = EmptyUFM
707 filter_tree f _ = panic "filter_tree failed"
708 \end{code}
709
710 %************************************************************************
711 %*                                                                      *
712 \subsubsection{The @UniqFM@ type, and signatures for the functions}
713 %*                                                                      *
714 %************************************************************************
715
716 Now some Utilities;
717
718 This is the information that is held inside a NodeUFM, packaged up for
719 consumer use.
720
721 \begin{code}
722 data NodeUFMData
723   = NodeUFMData FAST_INT
724                 FAST_INT
725 \end{code}
726
727 This is the information used when computing new NodeUFMs.
728
729 \begin{code}
730 data Side = Leftt | Rightt -- NB: avoid 1.3 names "Left" and "Right"
731 data CommonRoot
732   = LeftRoot  Side      -- which side is the right down ?
733   | RightRoot Side      -- which side is the left down ?
734   | SameRoot            -- they are the same !
735   | NewRoot NodeUFMData -- here's the new, common, root
736             Bool        -- do you need to swap left and right ?
737 \end{code}
738
739 This specifies the relationship between NodeUFMData and CalcNodeUFMData.
740
741 \begin{code}
742 indexToRoot :: FAST_INT -> NodeUFMData
743
744 indexToRoot i
745   = let
746         l = (ILIT(1) :: FAST_INT)
747     in
748     NodeUFMData (((i `shiftR_` l) `shiftL_` l) _ADD_ ILIT(1)) l
749
750 getCommonNodeUFMData :: NodeUFMData -> NodeUFMData -> NodeUFMData
751
752 getCommonNodeUFMData (NodeUFMData i p) (NodeUFMData i2 p2)
753   | p _EQ_ p2   = getCommonNodeUFMData_ p j j2
754   | p _LT_ p2   = getCommonNodeUFMData_ p2 (j _QUOT_ (p2 _QUOT_ p)) j2
755   | otherwise   = getCommonNodeUFMData_ p j (j2 _QUOT_ (p _QUOT_ p2))
756   where
757     l  = (ILIT(1) :: FAST_INT)
758     j  = i  _QUOT_ (p  `shiftL_` l)
759     j2 = i2 _QUOT_ (p2 `shiftL_` l)
760
761     getCommonNodeUFMData_ :: FAST_INT -> FAST_INT -> FAST_INT -> NodeUFMData
762
763     getCommonNodeUFMData_ p j j_
764       | j _EQ_ j_
765       = NodeUFMData (((j `shiftL_` l) _ADD_ l) _MUL_ p) p
766       | otherwise
767       = getCommonNodeUFMData_ (p `shiftL_`  l) (j `shiftR_` l) (j_ `shiftR_` l)
768
769 ask_about_common_ancestor :: NodeUFMData -> NodeUFMData -> CommonRoot
770
771 ask_about_common_ancestor x@(NodeUFMData j p) y@(NodeUFMData j2 p2)
772   | j _EQ_ j2 = SameRoot
773   | otherwise
774   = case getCommonNodeUFMData x y of
775       nd@(NodeUFMData j3 p3)
776         | j3 _EQ_ j  -> LeftRoot (decideSide (j _GT_ j2))
777         | j3 _EQ_ j2 -> RightRoot (decideSide (j _LT_ j2))
778         | otherwise   -> NewRoot nd (j _GT_ j2)
779     where
780         decideSide :: Bool -> Side
781         decideSide True  = Leftt
782         decideSide False = Rightt
783 \end{code}
784
785 This might be better in Util.lhs ?
786
787
788 Now the bit twiddling functions.
789 \begin{code}
790 shiftL_ :: FAST_INT -> FAST_INT -> FAST_INT
791 shiftR_ :: FAST_INT -> FAST_INT -> FAST_INT
792
793 #if __GLASGOW_HASKELL__
794 {-# INLINE shiftL_ #-}
795 {-# INLINE shiftR_ #-}
796 shiftL_ n p = word2Int#((int2Word# n) `shiftL#` p)
797 shiftR_ n p = word2Int#((int2Word# n) `shiftr` p)
798   where
799     shiftr x y = shiftRA# x y
800
801 #else {- not GHC -}
802 shiftL_ n p = n * (2 ^ p)
803 shiftR_ n p = n `quot` (2 ^ p)
804
805 #endif {- not GHC -}
806 \end{code}
807
808 \begin{code}
809 use_snd :: a -> b -> b
810 use_snd a b = b
811 \end{code}