@@ -266,6 +266,7 @@ module Data.IntMap.Internal (
266
266
, natFromInt
267
267
, intFromNat
268
268
, link
269
+ , linkWithMask
269
270
, bin
270
271
, binCheckLeft
271
272
, binCheckRight
@@ -3111,8 +3112,8 @@ fromListWithKey f xs
3111
3112
-- > fromAscList [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "b")]
3112
3113
3113
3114
fromAscList :: [(Key ,a )] -> IntMap a
3114
- fromAscList xs
3115
- = fromAscListWithKey ( \ _ x _ -> x) xs
3115
+ fromAscList = fromMonoListWithKey Nondistinct ( \ _ x _ -> x)
3116
+ {-# NOINLINE fromAscList #-}
3116
3117
3117
3118
-- | /O(n)/. Build a map from a list of key\/value pairs where
3118
3119
-- the keys are in ascending order, with a combining function on equal keys.
@@ -3121,8 +3122,8 @@ fromAscList xs
3121
3122
-- > fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "ba")]
3122
3123
3123
3124
fromAscListWith :: (a -> a -> a ) -> [(Key ,a )] -> IntMap a
3124
- fromAscListWith f xs
3125
- = fromAscListWithKey ( \ _ x y -> f x y) xs
3125
+ fromAscListWith f = fromMonoListWithKey Nondistinct ( \ _ x y -> f x y)
3126
+ {-# NOINLINE fromAscListWith #-}
3126
3127
3127
3128
-- | /O(n)/. Build a map from a list of key\/value pairs where
3128
3129
-- the keys are in ascending order, with a combining function on equal keys.
@@ -3132,50 +3133,80 @@ fromAscListWith f xs
3132
3133
-- > fromAscListWithKey f [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "5:b|a")]
3133
3134
3134
3135
fromAscListWithKey :: (Key -> a -> a -> a ) -> [(Key ,a )] -> IntMap a
3135
- fromAscListWithKey _ [] = Nil
3136
- fromAscListWithKey f (x0 : xs0) = fromDistinctAscList (combineEq x0 xs0)
3137
- where
3138
- -- [combineEq f xs] combines equal elements with function [f] in an ordered list [xs]
3139
- combineEq z [] = [z]
3140
- combineEq z@ (kz,zz) (x@ (kx,xx): xs)
3141
- | kx== kz = let yy = f kx xx zz in combineEq (kx,yy) xs
3142
- | otherwise = z: combineEq x xs
3136
+ fromAscListWithKey f = fromMonoListWithKey Nondistinct f
3137
+ {-# NOINLINE fromAscListWithKey #-}
3143
3138
3144
3139
-- | /O(n)/. Build a map from a list of key\/value pairs where
3145
3140
-- the keys are in ascending order and all distinct.
3146
3141
-- /The precondition (input list is strictly ascending) is not checked./
3147
3142
--
3148
3143
-- > fromDistinctAscList [(3,"b"), (5,"a")] == fromList [(3, "b"), (5, "a")]
3149
3144
3150
- #if __GLASGOW_HASKELL__
3151
- fromDistinctAscList :: forall a . [(Key ,a )] -> IntMap a
3152
- #else
3153
- fromDistinctAscList :: [(Key ,a )] -> IntMap a
3154
- #endif
3155
- fromDistinctAscList [] = Nil
3156
- fromDistinctAscList (z0 : zs0) = work z0 zs0 Nada
3157
- where
3158
- work (kx,vx) [] stk = finish kx (Tip kx vx) stk
3159
- work (kx,vx) (z@ (kz,_): zs) stk = reduce z zs (branchMask kx kz) kx (Tip kx vx) stk
3160
-
3161
- #if __GLASGOW_HASKELL__
3162
- reduce :: (Key ,a ) -> [(Key ,a )] -> Mask -> Prefix -> IntMap a -> Stack a -> IntMap a
3163
- #endif
3164
- reduce z zs _ px tx Nada = work z zs (Push px tx Nada )
3165
- reduce z zs m px tx stk@ (Push py ty stk') =
3166
- let mxy = branchMask px py
3167
- pxy = mask px mxy
3168
- in if shorter m mxy
3169
- then reduce z zs m pxy (Bin pxy mxy ty tx) stk'
3170
- else work z zs (Push px tx stk)
3171
-
3172
- finish _ t Nada = t
3173
- finish px tx (Push py ty stk) = finish p (link py ty px tx) stk
3174
- where m = branchMask px py
3175
- p = mask px m
3145
+ fromDistinctAscList :: [(Key ,a )] -> IntMap a
3146
+ fromDistinctAscList = fromMonoListWithKey Distinct (\ _ x _ -> x)
3147
+ {-# NOINLINE fromDistinctAscList #-}
3176
3148
3177
- data Stack a = Push {- # UNPACK #-} !Prefix ! (IntMap a ) ! (Stack a ) | Nada
3149
+ -- | /O(n)/. Build a map from a list of key\/value pairs with monotonic keys
3150
+ -- and a combining function.
3151
+ --
3152
+ -- The precise conditions under which this function works are subtle:
3153
+ -- For any branch mask, keys with the same prefix w.r.t. the branch
3154
+ -- mask must occur consecutively in the list.
3178
3155
3156
+ fromMonoListWithKey :: Distinct -> (Key -> a -> a -> a ) -> [(Key ,a )] -> IntMap a
3157
+ fromMonoListWithKey distinct f = go
3158
+ where
3159
+ go [] = Nil
3160
+ go ((kx,vx) : zs1) = addAll' kx vx zs1
3161
+
3162
+ -- `addAll'` collects all keys equal to `kx` into a single value,
3163
+ -- and then proceeds with `addAll`.
3164
+ addAll' ! kx vx []
3165
+ = Tip kx vx
3166
+ addAll' ! kx vx ((ky,vy) : zs)
3167
+ | Nondistinct <- distinct, kx == ky
3168
+ = let v = f kx vy vx in addAll' ky v zs
3169
+ -- inlined: | otherwise = addAll kx (Tip kx vx) (ky : zs)
3170
+ | m <- branchMask kx ky
3171
+ , Inserted ty zs' <- addMany' m ky vy zs
3172
+ = addAll kx (linkWithMask m ky ty {- kx-} (Tip kx vx)) zs'
3173
+
3174
+ -- for `addAll` and `addMany`, kx is /a/ key inside the tree `tx`
3175
+ -- `addAll` consumes the rest of the list, adding to the tree `tx`
3176
+ addAll ! kx ! tx []
3177
+ = tx
3178
+ addAll ! kx ! tx ((ky,vy) : zs)
3179
+ | m <- branchMask kx ky
3180
+ , Inserted ty zs' <- addMany' m ky vy zs
3181
+ = addAll kx (linkWithMask m ky ty {- kx-} tx) zs'
3182
+
3183
+ -- `addMany'` is similar to `addAll'`, but proceeds with `addMany'`.
3184
+ addMany' ! m ! kx vx []
3185
+ = Inserted (Tip kx vx) []
3186
+ addMany' ! m ! kx vx zs0@ ((ky,vy) : zs)
3187
+ | Nondistinct <- distinct, kx == ky
3188
+ = let v = f kx vy vx in addMany' m ky v zs
3189
+ -- inlined: | otherwise = addMany m kx (Tip kx vx) (ky : zs)
3190
+ | mask kx m /= mask ky m
3191
+ = Inserted (Tip kx vx) zs0
3192
+ | mxy <- branchMask kx ky
3193
+ , Inserted ty zs' <- addMany' mxy ky vy zs
3194
+ = addMany m kx (linkWithMask mxy ky ty {- kx-} (Tip kx vx)) zs'
3195
+
3196
+ -- `addAll` adds to `tx` all keys whose prefix w.r.t. `m` agrees with `kx`.
3197
+ addMany ! m ! kx tx []
3198
+ = Inserted tx []
3199
+ addMany ! m ! kx tx zs0@ ((ky,vy) : zs)
3200
+ | mask kx m /= mask ky m
3201
+ = Inserted tx zs0
3202
+ | mxy <- branchMask kx ky
3203
+ , Inserted ty zs' <- addMany' mxy ky vy zs
3204
+ = addMany m kx (linkWithMask mxy ky ty {- kx-} tx) zs'
3205
+ {-# INLINE fromMonoListWithKey #-}
3206
+
3207
+ data Inserted a = Inserted ! (IntMap a ) ! [(Key ,a )]
3208
+
3209
+ data Distinct = Distinct | Nondistinct
3179
3210
3180
3211
{- -------------------------------------------------------------------
3181
3212
Eq
@@ -3297,13 +3328,17 @@ INSTANCE_TYPEABLE1(IntMap)
3297
3328
Link
3298
3329
--------------------------------------------------------------------}
3299
3330
link :: Prefix -> IntMap a -> Prefix -> IntMap a -> IntMap a
3300
- link p1 t1 p2 t2
3331
+ link p1 t1 p2 t2 = linkWithMask (branchMask p1 p2) p1 t1 {- p2-} t2
3332
+ {-# INLINE link #-}
3333
+
3334
+ -- `linkWithMask` is useful when the `branchMask` has already been computed
3335
+ linkWithMask :: Mask -> Prefix -> IntMap a -> IntMap a -> IntMap a
3336
+ linkWithMask m p1 t1 {- p2-} t2
3301
3337
| zero p1 m = Bin p m t1 t2
3302
3338
| otherwise = Bin p m t2 t1
3303
3339
where
3304
- m = branchMask p1 p2
3305
3340
p = mask p1 m
3306
- {-# INLINE link #-}
3341
+ {-# INLINE linkWithMask #-}
3307
3342
3308
3343
{- -------------------------------------------------------------------
3309
3344
@bin@ assures that we never have empty trees within a tree.
0 commit comments