@@ -74,7 +74,7 @@ import Control.Monad.Primitive
7474import Control.Monad.ST
7575import Control.Monad.Zip
7676import Data.Data
77- import Data.Foldable
77+ import Data.Foldable as Foldable
7878import Data.Functor.Identity
7979#if !(MIN_VERSION_base(4,11,0))
8080import Data.Monoid
@@ -118,7 +118,7 @@ instance IsList (SmallArray a) where
118118 type Item (SmallArray a ) = a
119119 fromListN n l = SmallArray (fromListN n l)
120120 fromList l = SmallArray (fromList l)
121- toList ( SmallArray a) = toList a
121+ toList a = Foldable. toList a
122122#endif
123123#endif
124124
@@ -447,19 +447,27 @@ instance Eq a => Eq (SmallArray a) where
447447 sa1 == sa2 = length sa1 == length sa2 && loop (length sa1 - 1 )
448448 where
449449 loop i
450- | i < 0 = True
451- | otherwise = indexSmallArray sa1 i == indexSmallArray sa2 i && loop (i- 1 )
450+ | i < 0
451+ = True
452+ | (# x # ) <- indexSmallArray## sa1 i
453+ , (# y # ) <- indexSmallArray## sa2 i
454+ = x == y && loop (i- 1 )
452455
453456instance Eq (SmallMutableArray s a ) where
454457 SmallMutableArray sma1# == SmallMutableArray sma2# =
455458 isTrue# (sameSmallMutableArray# sma1# sma2# )
456459
457460instance Ord a => Ord (SmallArray a ) where
458- compare sl sr = fix ? 0 $ \ go i ->
459- if i < l
460- then compare (indexSmallArray sl i) (indexSmallArray sr i) <> go (i+ 1 )
461- else compare (length sl) (length sr)
462- where l = length sl `min` length sr
461+ compare a1 a2 = loop 0
462+ where
463+ mn = length a1 `min` length a2
464+ loop i
465+ | i < mn
466+ , (# x1 # ) <- indexSmallArray## a1 i
467+ , (# x2 # ) <- indexSmallArray## a2 i
468+ = compare x1 x2 `mappend` loop (i+ 1 )
469+ | otherwise = compare (length a1) (length a2)
470+
463471
464472instance Foldable SmallArray where
465473 -- Note: we perform the array lookups eagerly so we won't
@@ -597,8 +605,9 @@ traverseSmallArray f = \ !ary ->
597605instance Functor SmallArray where
598606 fmap f sa = createSmallArray (length sa) (die " fmap" " impossible" ) $ \ smb ->
599607 fix ? 0 $ \ go i ->
600- when (i < length sa) $
601- writeSmallArray smb i (f $ indexSmallArray sa i) *> go (i+ 1 )
608+ when (i < length sa) $ do
609+ x <- indexSmallArrayM sa i
610+ writeSmallArray smb i (f x) *> go (i+ 1 )
602611 {-# INLINE fmap #-}
603612
604613 x <$ sa = createSmallArray (length sa) x noOp
@@ -613,22 +622,23 @@ instance Applicative SmallArray where
613622 where
614623 la = length sa ; lb = length sb
615624
616- sa <* sb = createSmallArray (la * lb ) (indexSmallArray sa $ la - 1 ) $ \ sma ->
617- fix ? 0 $ \ outer i -> when (i < la - 1 ) $ do
618- let a = indexSmallArray sa i
619- fix ? 0 $ \ inner j ->
620- when (j < lb) $
621- writeSmallArray sma (la * i + j) a *> inner (j + 1 )
622- outer $ i+ 1
623- where
624- la = length sa ; lb = length sb
625+ a <* b = createSmallArray (sza * szb ) (die " <* " " impossible " ) $ \ ma ->
626+ let fill off i e = when (i < szb ) $
627+ writeSmallArray ma (off + i) e >> fill off (i + 1 ) e
628+ go i = when (i < sza) $ do
629+ x <- indexSmallArrayM a i
630+ fill (i * szb) 0 x
631+ go ( i+ 1 )
632+ in go 0
633+ where sza = sizeofSmallArray a ; szb = sizeofSmallArray b
625634
626635 sf <*> sx = createSmallArray (lf* lx) (die " <*>" " impossible" ) $ \ smb ->
627636 fix ? 0 $ \ outer i -> when (i < lf) $ do
628- let f = indexSmallArray sf i
637+ f <- indexSmallArrayM sf i
629638 fix ? 0 $ \ inner j ->
630- when (j < lx) $
631- writeSmallArray smb (lf* i + j) (f $ indexSmallArray sx j)
639+ when (j < lx) $ do
640+ x <- indexSmallArrayM sx j
641+ writeSmallArray smb (lf* i + j) (f x)
632642 *> inner (j+ 1 )
633643 outer $ i+ 1
634644 where
@@ -648,20 +658,41 @@ instance Alternative SmallArray where
648658 some sa | null sa = emptySmallArray
649659 | otherwise = die " some" " infinite arrays are not well defined"
650660
661+ data ArrayStack a
662+ = PushArray ! (SmallArray a ) ! (ArrayStack a )
663+ | EmptyStack
664+ -- TODO: This isn't terribly efficient. It would be better to wrap
665+ -- ArrayStack with a type like
666+ --
667+ -- data NES s a = NES !Int !(SmallMutableArray s a) !(ArrayStack a)
668+ --
669+ -- We'd copy incoming arrays into the mutable array until we would
670+ -- overflow it. Then we'd freeze it, push it on the stack, and continue.
671+ -- Any sufficiently large incoming arrays would go straight on the stack.
672+ -- Such a scheme would make the stack much more compact in the case
673+ -- of many small arrays.
674+
651675instance Monad SmallArray where
652676 return = pure
653677 (>>) = (*>)
654678
655- sa >>= f = collect 0 [] (la- 1 )
679+ sa >>= f = collect 0 EmptyStack (la- 1 )
656680 where
657681 la = length sa
658682 collect sz stk i
659683 | i < 0 = createSmallArray sz (die " >>=" " impossible" ) $ fill 0 stk
660- | otherwise = let sb = f $ indexSmallArray sa i in
661- collect (sz + length sb) (sb: stk) (i- 1 )
662-
663- fill _ [ ] _ = return ()
664- fill off (sb: sbs) smb =
684+ | (# x # ) <- indexSmallArray## sa i
685+ , let sb = f x
686+ lsb = length sb
687+ -- If we don't perform this check, we could end up allocating
688+ -- a stack full of empty arrays if someone is filtering most
689+ -- things out. So we refrain from pushing empty arrays.
690+ = if lsb == 0
691+ then collect sz stk (i- 1 )
692+ else collect (sz + lsb) (PushArray sb stk) (i- 1 )
693+
694+ fill _ EmptyStack _ = return ()
695+ fill off (PushArray sb sbs) smb =
665696 copySmallArray smb off sb 0 (length sb)
666697 *> fill (off + length sb) sbs smb
667698
@@ -674,9 +705,11 @@ instance MonadPlus SmallArray where
674705zipW :: String -> (a -> b -> c ) -> SmallArray a -> SmallArray b -> SmallArray c
675706zipW nm = \ f sa sb -> let mn = length sa `min` length sb in
676707 createSmallArray mn (die nm " impossible" ) $ \ mc ->
677- fix ? 0 $ \ go i -> when (i < mn) $
678- writeSmallArray mc i (f (indexSmallArray sa i) (indexSmallArray sb i))
679- *> go (i+ 1 )
708+ fix ? 0 $ \ go i -> when (i < mn) $ do
709+ x <- indexSmallArrayM sa i
710+ y <- indexSmallArrayM sb i
711+ writeSmallArray mc i (f x y)
712+ go (i+ 1 )
680713{-# INLINE zipW #-}
681714
682715instance MonadZip SmallArray where
@@ -696,7 +729,14 @@ instance MonadZip SmallArray where
696729 <*> unsafeFreezeSmallArray smb
697730
698731instance MonadFix SmallArray where
699- mfix f = fromList . mfix $ toList . f
732+ mfix f = createSmallArray (sizeofSmallArray (f err))
733+ (die " mfix" " impossible" ) $ flip fix 0 $
734+ \ r ! i ! mary -> when (i < sz) $ do
735+ writeSmallArray mary i (fix (\ xi -> f xi `indexSmallArray` i))
736+ r (i + 1 ) mary
737+ where
738+ sz = sizeofSmallArray (f err)
739+ err = error " mfix for Data.Primitive.SmallArray applied to strict function."
700740
701741#if MIN_VERSION_base(4,9,0)
702742instance Sem. Semigroup (SmallArray a ) where
@@ -723,7 +763,7 @@ instance IsList (SmallArray a) where
723763 [] -> pure ()
724764 x: xs -> writeSmallArray sma i x *> go (i+ 1 ) xs
725765 fromList l = fromListN (length l) l
726- toList sa = indexSmallArray sa <$> [ 0 .. length sa - 1 ]
766+ toList = Foldable. toList
727767
728768instance Show a => Show (SmallArray a ) where
729769 showsPrec p sa = showParen (p > 10 ) $
0 commit comments