From 5c3bd80bef48a5e3da8280b2f440b7b6ce2443a1 Mon Sep 17 00:00:00 2001 From: Simon Jakobi Date: Fri, 6 Feb 2026 12:27:57 +0100 Subject: [PATCH 1/2] Add sameSmallArray and sameSmallMutableArray Resolves #403. --- Data/Primitive/SmallArray.hs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Data/Primitive/SmallArray.hs b/Data/Primitive/SmallArray.hs index b33833a..f530b64 100644 --- a/Data/Primitive/SmallArray.hs +++ b/Data/Primitive/SmallArray.hs @@ -56,6 +56,8 @@ module Data.Primitive.SmallArray , sizeofSmallArray , getSizeofSmallMutableArray , sizeofSmallMutableArray + , sameSmallArray + , sameSmallMutableArray #if MIN_VERSION_base(4,14,0) , shrinkSmallMutableArray , resizeSmallMutableArray @@ -311,6 +313,28 @@ unsafeThawSmallArray (SmallArray sa#) = (# s', sma# #) -> (# s', SmallMutableArray sma# #) {-# INLINE unsafeThawSmallArray #-} +-- | Check whether the two arrays refer to the same memory block. +sameSmallArray :: SmallArray a -> SmallArray a -> Bool +{-# INLINE sameSmallArray #-} +sameSmallArray (SmallArray sa1#) (SmallArray sa2#) = +#if MIN_VERSION_base(4,17,0) + isTrue# (sameSmallArray# sa1# sa2#) +#else + isTrue# + (reallyUnsafePtrEquality# (unsafeCoerce# sa1# :: ()) (unsafeCoerce# sa2# :: ())) +#endif + +-- | Check whether the two arrays refer to the same memory block. +sameSmallMutableArray :: SmallMutableArray s a -> SmallMutableArray s a -> Bool +{-# INLINE sameSmallMutableArray #-} +sameSmallMutableArray (SmallMutableArray sma1#) (SmallMutableArray sma2#) = +#if MIN_VERSION_base(4,17,0) + isTrue# (sameSmallMutableArray# sma1# sma2#) +#else + isTrue# + (reallyUnsafePtrEquality# (unsafeCoerce# sma1# :: ()) (unsafeCoerce# sma2# :: ())) +#endif + -- | Copy a slice of an immutable array into a mutable array. -- -- /Note:/ this function does not do bounds or overlap checking. @@ -525,7 +549,7 @@ instance Eq a => Eq (SmallArray a) where instance Eq (SmallMutableArray s a) where SmallMutableArray sma1# == SmallMutableArray sma2# = - isTrue# (sameSmallMutableArray# sma1# sma2#) + sameSmallMutableArray (SmallMutableArray sma1#) (SmallMutableArray sma2#) smallArrayLiftCompare :: (a -> b -> Ordering) -> SmallArray a -> SmallArray b -> Ordering smallArrayLiftCompare elemCompare a1 a2 = loop 0 From f83f2f7a252a62903bb98f990799348907f1c734 Mon Sep 17 00:00:00 2001 From: Simon Jakobi Date: Fri, 6 Feb 2026 18:17:18 +0100 Subject: [PATCH 2/2] Optimize Eq for SmallArray via pointer equality fast-path Use sameSmallArray to short-circuit (==) when two SmallArray values share the same underlying object. --- Data/Primitive/SmallArray.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Data/Primitive/SmallArray.hs b/Data/Primitive/SmallArray.hs index f530b64..8862be0 100644 --- a/Data/Primitive/SmallArray.hs +++ b/Data/Primitive/SmallArray.hs @@ -545,7 +545,7 @@ instance Eq1 SmallArray where liftEq = smallArrayLiftEq instance Eq a => Eq (SmallArray a) where - sa1 == sa2 = smallArrayLiftEq (==) sa1 sa2 + sa1 == sa2 = sameSmallArray sa1 sa2 || smallArrayLiftEq (==) sa1 sa2 instance Eq (SmallMutableArray s a) where SmallMutableArray sma1# == SmallMutableArray sma2# =