Skip to content

Commit 269f53e

Browse files
authored
Revert union, difference, etc. complexity changes (#958)
As discussed in #870, the complexities for union, difference, etc. on Set and Map were changed in #830 to fix some partiality in the expressions, but along the way new partiality was introduced, and useful special cases like m = 1 get incorrect complexity values from the new formulas. The original formula was as stated in the original paper: https://dl.acm.org/doi/10.1145/322123.322127 and this holds for 0 < m <= n, which seems sufficient to me. (The m=0 case is excluded, but for m=0 nothing needs to be done anyway. This contrary to the m=1 case, in which useful work with very specific complexity (namely, O(log(n))) needs to be done.) This commit reverts all occurrences of the modified complexity formula back to the original one.
1 parent 9d395e4 commit 269f53e

File tree

3 files changed

+25
-25
lines changed

3 files changed

+25
-25
lines changed

containers/src/Data/Map/Internal.hs

+14-14
Original file line numberDiff line numberDiff line change
@@ -1811,7 +1811,7 @@ unionsWith f ts
18111811
{-# INLINABLE unionsWith #-}
18121812
#endif
18131813

1814-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\).
1814+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\).
18151815
-- The expression (@'union' t1 t2@) takes the left-biased union of @t1@ and @t2@.
18161816
-- It prefers @t1@ when duplicate keys are encountered,
18171817
-- i.e. (@'union' == 'unionWith' 'const'@).
@@ -1835,7 +1835,7 @@ union t1@(Bin _ k1 x1 l1 r1) t2 = case split k1 t2 of
18351835
{--------------------------------------------------------------------
18361836
Union with a combining function
18371837
--------------------------------------------------------------------}
1838-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Union with a combining function.
1838+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Union with a combining function.
18391839
--
18401840
-- > unionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "aA"), (7, "C")]
18411841

@@ -1855,7 +1855,7 @@ unionWith f (Bin _ k1 x1 l1 r1) t2 = case splitLookup k1 t2 of
18551855
{-# INLINABLE unionWith #-}
18561856
#endif
18571857

1858-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\).
1858+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\).
18591859
-- Union with a combining function.
18601860
--
18611861
-- > let f key left_value right_value = (show key) ++ ":" ++ left_value ++ "|" ++ right_value
@@ -1886,7 +1886,7 @@ unionWithKey f (Bin _ k1 x1 l1 r1) t2 = case splitLookup k1 t2 of
18861886
-- relies on doing it the way we do, and it's not clear whether that
18871887
-- bound holds the other way.
18881888

1889-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Difference of two maps.
1889+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Difference of two maps.
18901890
-- Return elements of the first map not existing in the second map.
18911891
--
18921892
-- > difference (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 3 "b"
@@ -1905,7 +1905,7 @@ difference t1 (Bin _ k _ l2 r2) = case split k t1 of
19051905
{-# INLINABLE difference #-}
19061906
#endif
19071907

1908-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Remove all keys in a 'Set' from a 'Map'.
1908+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Remove all keys in a 'Set' from a 'Map'.
19091909
--
19101910
-- @
19111911
-- m \`withoutKeys\` s = 'filterWithKey' (\\k _ -> k ``Set.notMember`` s) m
@@ -1964,7 +1964,7 @@ differenceWithKey f =
19641964
{--------------------------------------------------------------------
19651965
Intersection
19661966
--------------------------------------------------------------------}
1967-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Intersection of two maps.
1967+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Intersection of two maps.
19681968
-- Return data in the first map for the keys existing in both maps.
19691969
-- (@'intersection' m1 m2 == 'intersectionWith' 'const' m1 m2@).
19701970
--
@@ -1986,7 +1986,7 @@ intersection t1@(Bin _ k x l1 r1) t2
19861986
{-# INLINABLE intersection #-}
19871987
#endif
19881988

1989-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Restrict a 'Map' to only those keys
1989+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Restrict a 'Map' to only those keys
19901990
-- found in a 'Set'.
19911991
--
19921992
-- @
@@ -2011,7 +2011,7 @@ restrictKeys m@(Bin _ k x l1 r1) s
20112011
{-# INLINABLE restrictKeys #-}
20122012
#endif
20132013

2014-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Intersection with a combining function.
2014+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Intersection with a combining function.
20152015
--
20162016
-- > intersectionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "aA"
20172017

@@ -2031,7 +2031,7 @@ intersectionWith f (Bin _ k x1 l1 r1) t2 = case mb of
20312031
{-# INLINABLE intersectionWith #-}
20322032
#endif
20332033

2034-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Intersection with a combining function.
2034+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Intersection with a combining function.
20352035
--
20362036
-- > let f k al ar = (show k) ++ ":" ++ al ++ "|" ++ ar
20372037
-- > intersectionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "5:a|A"
@@ -2053,7 +2053,7 @@ intersectionWithKey f (Bin _ k x1 l1 r1) t2 = case mb of
20532053
{--------------------------------------------------------------------
20542054
Disjoint
20552055
--------------------------------------------------------------------}
2056-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Check whether the key sets of two
2056+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Check whether the key sets of two
20572057
-- maps are disjoint (i.e., their 'intersection' is empty).
20582058
--
20592059
-- > disjoint (fromList [(2,'a')]) (fromList [(1,()), (3,())]) == True
@@ -2752,7 +2752,7 @@ mergeWithKey f g1 g2 = go
27522752
{--------------------------------------------------------------------
27532753
Submap
27542754
--------------------------------------------------------------------}
2755-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\).
2755+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\).
27562756
-- This function is defined as (@'isSubmapOf' = 'isSubmapOfBy' (==)@).
27572757
--
27582758
isSubmapOf :: (Ord k,Eq a) => Map k a -> Map k a -> Bool
@@ -2761,7 +2761,7 @@ isSubmapOf m1 m2 = isSubmapOfBy (==) m1 m2
27612761
{-# INLINABLE isSubmapOf #-}
27622762
#endif
27632763

2764-
{- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\).
2764+
{- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\).
27652765
The expression (@'isSubmapOfBy' f t1 t2@) returns 'True' if
27662766
all keys in @t1@ are in tree @t2@, and when @f@ returns 'True' when
27672767
applied to their respective values. For example, the following
@@ -2810,7 +2810,7 @@ submap' f (Bin _ kx x l r) t
28102810
{-# INLINABLE submap' #-}
28112811
#endif
28122812

2813-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Is this a proper submap? (ie. a submap but not equal).
2813+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Is this a proper submap? (ie. a submap but not equal).
28142814
-- Defined as (@'isProperSubmapOf' = 'isProperSubmapOfBy' (==)@).
28152815
isProperSubmapOf :: (Ord k,Eq a) => Map k a -> Map k a -> Bool
28162816
isProperSubmapOf m1 m2
@@ -2819,7 +2819,7 @@ isProperSubmapOf m1 m2
28192819
{-# INLINABLE isProperSubmapOf #-}
28202820
#endif
28212821

2822-
{- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Is this a proper submap? (ie. a submap but not equal).
2822+
{- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Is this a proper submap? (ie. a submap but not equal).
28232823
The expression (@'isProperSubmapOfBy' f m1 m2@) returns 'True' when
28242824
@keys m1@ and @keys m2@ are not equal,
28252825
all keys in @m1@ are in @m2@, and when @f@ returns 'True' when

containers/src/Data/Map/Strict/Internal.hs

+4-4
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,7 @@ unionsWith f ts
980980
{--------------------------------------------------------------------
981981
Union with a combining function
982982
--------------------------------------------------------------------}
983-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Union with a combining function.
983+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Union with a combining function.
984984
--
985985
-- > unionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == fromList [(3, "b"), (5, "aA"), (7, "C")]
986986

@@ -996,7 +996,7 @@ unionWith f (Bin _ k1 x1 l1 r1) t2 = case splitLookup k1 t2 of
996996
{-# INLINABLE unionWith #-}
997997
#endif
998998

999-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\).
999+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\).
10001000
-- Union with a combining function.
10011001
--
10021002
-- > let f key left_value right_value = (show key) ++ ":" ++ left_value ++ "|" ++ right_value
@@ -1054,7 +1054,7 @@ differenceWithKey f = merge preserveMissing dropMissing (zipWithMaybeMatched f)
10541054
Intersection
10551055
--------------------------------------------------------------------}
10561056

1057-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Intersection with a combining function.
1057+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Intersection with a combining function.
10581058
--
10591059
-- > intersectionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "aA"
10601060

@@ -1072,7 +1072,7 @@ intersectionWith f (Bin _ k x1 l1 r1) t2 = case mb of
10721072
{-# INLINABLE intersectionWith #-}
10731073
#endif
10741074

1075-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Intersection with a combining function.
1075+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Intersection with a combining function.
10761076
--
10771077
-- > let f k al ar = (show k) ++ ":" ++ al ++ "|" ++ ar
10781078
-- > intersectionWithKey f (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "5:a|A"

containers/src/Data/Set/Internal.hs

+7-7
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ import Language.Haskell.TH ()
269269
--------------------------------------------------------------------}
270270
infixl 9 \\ --
271271

272-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). See 'difference'.
272+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). See 'difference'.
273273
(\\) :: Ord a => Set a -> Set a -> Set a
274274
m1 \\ m2 = difference m1 m2
275275
#if __GLASGOW_HASKELL__
@@ -654,7 +654,7 @@ alteredSet x0 s0 = go x0 s0
654654
{--------------------------------------------------------------------
655655
Subset
656656
--------------------------------------------------------------------}
657-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\).
657+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\).
658658
-- @(s1 \`isProperSubsetOf\` s2)@ indicates whether @s1@ is a
659659
-- proper subset of @s2@.
660660
--
@@ -669,7 +669,7 @@ isProperSubsetOf s1 s2
669669
#endif
670670

671671

672-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\).
672+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\).
673673
-- @(s1 \`isSubsetOf\` s2)@ indicates whether @s1@ is a subset of @s2@.
674674
--
675675
-- @
@@ -724,7 +724,7 @@ isSubsetOfX (Bin _ x l r) t
724724
{--------------------------------------------------------------------
725725
Disjoint
726726
--------------------------------------------------------------------}
727-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Check whether two sets are disjoint
727+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Check whether two sets are disjoint
728728
-- (i.e., their intersection is empty).
729729
--
730730
-- > disjoint (fromList [2,4,6]) (fromList [1,3]) == True
@@ -815,7 +815,7 @@ unions = Foldable.foldl' union empty
815815
{-# INLINABLE unions #-}
816816
#endif
817817

818-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). The union of two sets, preferring the first set when
818+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). The union of two sets, preferring the first set when
819819
-- equal elements are encountered.
820820
union :: Ord a => Set a -> Set a -> Set a
821821
union t1 Tip = t1
@@ -835,7 +835,7 @@ union t1@(Bin _ x l1 r1) t2 = case splitS x t2 of
835835
{--------------------------------------------------------------------
836836
Difference
837837
--------------------------------------------------------------------}
838-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). Difference of two sets.
838+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). Difference of two sets.
839839
--
840840
-- Return elements of the first set not existing in the second set.
841841
--
@@ -856,7 +856,7 @@ difference t1 (Bin _ x l2 r2) = case split x t1 of
856856
{--------------------------------------------------------------------
857857
Intersection
858858
--------------------------------------------------------------------}
859-
-- | \(O\bigl(m \log\bigl(\frac{n+1}{m+1}\bigr)\bigr), \; m \leq n\). The intersection of two sets.
859+
-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). The intersection of two sets.
860860
-- Elements of the result come from the first set, so for example
861861
--
862862
-- > import qualified Data.Set as S

0 commit comments

Comments
 (0)