Skip to content

Commit 9fd024e

Browse files
committed
Introduce size-aware 'insertWithInternal' function
1 parent a8b7274 commit 9fd024e

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

Data/HashMap/Base.hs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,50 @@ insertWith f k0 v0 m0 = go h0 k0 v0 0 m0
709709
| otherwise = go h k x s $ BitmapIndexed (mask hy s) (A.singleton t)
710710
{-# INLINABLE insertWith #-}
711711

712+
-- | /O(log n)/ Associate the value with the key in this map. If
713+
-- this map previously contained a mapping for the key, the old value
714+
-- is replaced by the result of applying the given function to the new
715+
-- and old value. Example:
716+
--
717+
-- > insertWithInternal f k v map
718+
-- > where f new old = new + old
719+
insertWithInternal :: (Eq k, Hashable k) => (v -> v -> v) -> k -> v -> HashMap k v
720+
-> (Int, HashMap k v)
721+
insertWithInternal f k0 v0 m0 = go h0 k0 v0 0 m0
722+
where
723+
h0 = hash k0
724+
go !h !k x !_ Empty = (1, Leaf h (L k x))
725+
go h k x s (Leaf hy l@(L ky y))
726+
| hy == h = if ky == k
727+
then (0, Leaf h (L k (f x y)))
728+
else (1, collision h l (L k x))
729+
| otherwise = (0, runST (two s h k x hy ky y))
730+
go h k x s (BitmapIndexed b ary)
731+
| b .&. m == 0 =
732+
let ary' = A.insert ary i $! Leaf h (L k x)
733+
in (1, bitmapIndexedOrFull (b .|. m) ary')
734+
| otherwise =
735+
let st = A.index ary i
736+
(sz, st') = go h k x (s+bitsPerSubkey) st
737+
ary' = A.update ary i $! st'
738+
in (sz, BitmapIndexed b ary')
739+
where m = mask h s
740+
i = sparseIndex b m
741+
go h k x s (Full ary) =
742+
let st = A.index ary i
743+
(sz, st') = go h k x (s+bitsPerSubkey) st
744+
ary' = update16 ary i $! st'
745+
in (sz, Full ary')
746+
where i = index h s
747+
go h k x s t@(Collision hy v)
748+
| h == hy =
749+
let !start = A.length v
750+
!newV = updateOrSnocWith const k x v
751+
!end = A.length newV
752+
in (end - start, Collision h newV)
753+
| otherwise = go h k x s $ BitmapIndexed (mask hy s) (A.singleton t)
754+
{-# INLINABLE insertWithInternal #-}
755+
712756
-- | In-place update version of insertWith
713757
unsafeInsertWith :: forall k v. (Eq k, Hashable k)
714758
=> (v -> v -> v) -> k -> v -> HashMap k v

0 commit comments

Comments
 (0)