@@ -320,7 +320,6 @@ import Data.Int (Int64)
320320import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef, IORef)
321321import Data.Maybe (fromJust, isJust, isNothing)
322322import Data.Word (Word32)
323−import Foreign.Ptr (Ptr)
324323import Foreign.Storable (Storable(..))
325324import GHC.Exts (SpecConstrAnnotation(..))
326325import GHC.Types (SPEC(..))
@@ -1793,6 +1792,8 @@ data SplitOnSeqState rb rh ck w fs s b x =
17931792 | SplitOnSeqDone
17941793
17951794 | SplitOnSeqEmpty s
1795+
1796+ | SplitOnSeqSingleInit s x
17961797 | SplitOnSeqSingle !fs s x
17971798
17981799 | SplitOnSeqWordInit s
@@ -1889,6 +1890,9 @@ splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
18891890 -- Single Pattern
18901891 -----------------
18911892
1893+ stepOuter _ (SplitOnSeqSingleInit _ _) =
1894+ error "This branch should not have hit"
1895+
18921896 stepOuter gst (SplitOnSeqSingle fs st pat) = do
18931897 res <- step (adaptState gst) st
18941898 case res of
@@ -2059,14 +2063,6 @@ splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
20592063 fs1 <- fstep fs old
20602064 skip $ SplitOnSeqKRDone (n - 1) fs1 rb rh1
20612065
2062−data SplitOnState1 s a =
2063− GO_START1
2064− | GO_EMPTY_PAT1 s
2065− | GO_SINGLE_PAT s a
2066− | GO_SHORT_PAT s
2067− | GO_KARP_RABIN s !(RB.Ring a) !(Ptr a)
2068− | GO_DONE1
2069−
20702066{-# INLINE_NORMAL splitSuffixOn #-}
20712067splitSuffixOn
20722068 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
@@ -2075,9 +2071,8 @@ splitSuffixOn
20752071 -> Fold m a b
20762072 -> Stream m a
20772073 -> Stream m b
2078−splitSuffixOn withSep patArr (Fold fstep initial done)
2079− (Stream step state) =
2080− Stream stepOuter GO_START1
2074+splitSuffixOn withSep patArr (Fold fstep initial done) (Stream step state) =
2075+ Stream stepOuter SplitOnSeqInit
20812076
20822077 where
20832078
@@ -2085,248 +2080,332 @@ splitSuffixOn withSep patArr (Fold fstep initial done)
20852080 maxIndex = patLen - 1
20862081 elemBits = sizeOf (undefined :: a) * 8
20872082
2083+ -- For word pattern case
2084+ wordMask :: Word
2085+ wordMask = (1 `shiftL` (elemBits * patLen)) - 1
2086+
2087+ elemMask :: Word
2088+ elemMask = (1 `shiftL` elemBits) - 1
2089+
2090+ wordPat :: Word
2091+ wordPat = wordMask .&. A.foldl' addToWord 0 patArr
2092+
2093+ addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
2094+
2095+ -- For Rabin-Karp search
2096+ k = 2891336453 :: Word32
2097+ coeff = k ^ patLen
2098+
2099+ addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
2100+
2101+ deltaCksum cksum old new =
2102+ addCksum cksum new - coeff * fromIntegral (fromEnum old)
2103+
2104+ -- XXX shall we use a random starting hash or 1 instead of 0?
2105+ patHash = A.foldl' addCksum 0 patArr
2106+
2107+ skip = return . Skip
2108+
20882109 {-# INLINE_LATE stepOuter #-}
2089− stepOuter _ GO_START1 =
2110+ stepOuter _ SplitOnSeqInit =
20902111 if patLen == 0
2091− then return $ Skip $ GO_EMPTY_PAT1 state
2112+ then return $ Skip $ SplitOnSeqEmpty state
20922113 else if patLen == 1
20932114 then do
2094− r <- liftIO $ (A.unsafeIndexIO patArr 0)
2095− return $ Skip $ GO_SINGLE_PAT state r
2115+ let !pat = A.unsafeIndex patArr 0
2116+ return $ Skip $ SplitOnSeqSingleInit state pat
20962117 else if sizeOf (undefined :: a) * patLen
2097− <= sizeOf (undefined :: Word)
2098− then return $ Skip $ GO_SHORT_PAT state
2118+ <= sizeOf (undefined :: Word)
2119+ then return $ Skip $ SplitOnSeqWordInit state
20992120 else do
2100− (rb, rhead) <- liftIO $ RB.new patLen
2101− return $ Skip $ GO_KARP_RABIN state rb rhead
2102−
2103− stepOuter gst (GO_SINGLE_PAT stt pat) = do
2104− -- This first part is the only difference between splitOn and
2105− -- splitSuffixOn.
2106− -- If the last element is a separator do not issue a blank segment.
2107− res <- step (adaptState gst) stt
2121+ (rb, rhead) <- liftIO $ RB.new patLen
2122+ skip $ SplitOnSeqKRInit 0 state rb rhead
2123+
2124+ stepOuter _ (SplitOnSeqYield x next) = return $ Yield x next
2125+
2126+ ---------------------------
2127+ -- Empty pattern
2128+ ---------------------------
2129+
2130+ stepOuter gst (SplitOnSeqEmpty st) = do
2131+ res <- step (adaptState gst) st
21082132 case res of
21092133 Yield x s -> do
21102134 acc <- initial
2135+ acc1 <- fstep acc x
2136+ r <- done acc1
2137+ skip $ SplitOnSeqYield r (SplitOnSeqEmpty s)
2138+ Skip s -> return $ Skip (SplitOnSeqEmpty s)
2139+ Stop -> return Stop
2140+
2141+ -----------------
2142+ -- Done
2143+ -----------------
2144+
2145+ stepOuter _ SplitOnSeqDone = return Stop
2146+
2147+ -----------------
2148+ -- Single Pattern
2149+ -----------------
2150+
2151+ stepOuter gst (SplitOnSeqSingleInit st pat) = do
2152+ res <- step (adaptState gst) st
2153+ case res of
2154+ Yield x s -> do
2155+ fs <- initial
21112156 if pat == x
21122157 then do
2113− acc' <- if withSep then fstep acc x else return acc
2114− done acc' >>= \r -> return $ Yield r (GO_SINGLE_PAT s pat)
2115− else fstep acc x >>= go SPEC s
2116− Skip s -> return $ Skip $ (GO_SINGLE_PAT s pat)
2117− Stop -> return Stop
2118−
2119− where
2158+ if withSep
2159+ then do
2160+ fs1 <- fstep fs x
2161+ r <- done fs1
2162+ let next = SplitOnSeqSingleInit s pat
2163+ skip $ SplitOnSeqYield r next
2164+ else do
2165+ r <- done fs
2166+ let next = SplitOnSeqSingleInit s pat
2167+ skip $ SplitOnSeqYield r next
2168+ else do
2169+ fs1 <- fstep fs x
2170+ skip $ SplitOnSeqSingle fs1 s pat
2171+ Skip s -> return $ Skip $ (SplitOnSeqSingleInit s pat)
2172+ Stop -> return Stop
21202173
2121− -- This is identical for splitOn and splitSuffixOn
2122− go !_ st !acc = do
2123− res <- step (adaptState gst) st
2124− case res of
2125− Yield x s -> do
2126− if pat == x
2174+ stepOuter gst (SplitOnSeqSingle fs st pat) = do
2175+ res <- step (adaptState gst) st
2176+ case res of
2177+ Yield x s -> do
2178+ if pat == x
2179+ then do
2180+ if withSep
21272181 then do
2128− acc' <- if withSep then fstep acc x else return acc
2129− r <- done acc'
2130− return $ Yield r (GO_SINGLE_PAT s pat)
2131− else fstep acc x >>= go SPEC s
2132− Skip s -> go SPEC s acc
2133− Stop -> done acc >>= \r -> return $ Yield r GO_DONE1
2182+ fs1 <- fstep fs x
2183+ r <- done fs1
2184+ let next = SplitOnSeqSingleInit s pat
2185+ skip $ SplitOnSeqYield r next
2186+ else do
2187+ r <- done fs
2188+ let next = SplitOnSeqSingleInit s pat
2189+ skip $ SplitOnSeqYield r next
2190+ else do
2191+ fs1 <- fstep fs x
2192+ return $ Skip $ (SplitOnSeqSingle fs1 s pat)
2193+ Skip s -> return $ Skip $ SplitOnSeqSingle fs s pat
2194+ Stop -> do
2195+ r <- done fs
2196+ return $ Skip $ SplitOnSeqYield r SplitOnSeqDone
21342197
2135− stepOuter gst (GO_SHORT_PAT stt) = do
2198+ ---------------------------
2199+ -- Short Pattern - Shift Or
2200+ ---------------------------
21362201
2137− -- Call "initial" only if the stream yields an element, otherwise we
2138− -- may call "initial" but never yield anything. initial may produce a
2139− -- side effect, therefore we will end up doing and discard a side
2140− -- effect.
2202+ stepOuter _ (SplitOnSeqWordDone 0 fs _) = do
2203+ r <- done fs
2204+ skip $ SplitOnSeqYield r SplitOnSeqDone
2205+ stepOuter _ (SplitOnSeqWordDone n fs wrd) = do
2206+ let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
2207+ fs1 <- fstep fs (toEnum $ fromIntegral old)
2208+ skip $ SplitOnSeqWordDone (n - 1) fs1 wrd
21412209
2142− let idx = 0
2143− let wrd = 0
2144− res <- step (adaptState gst) stt
2210+ stepOuter gst (SplitOnSeqWordInit st0) = do
2211+ res <- step (adaptState gst) st0
21452212 case res of
21462213 Yield x s -> do
2147− acc <- initial
2148− let wrd' = addToWord wrd x
2149− acc' <- if withSep then fstep acc x else return acc
2150− if idx == maxIndex
2214+ fs <- initial
2215+ let wrd = addToWord 0 x
2216+ if withSep
21512217 then do
2152− if wrd' .&. mask == patWord
2153− then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
2154− else go0 SPEC (idx + 1) wrd' s acc'
2155− else go0 SPEC (idx + 1) wrd' s acc'
2156− Skip s -> return $ Skip (GO_SHORT_PAT s)
2218+ fs1 <- fstep fs x
2219+ go SPEC 1 wrd s fs1
2220+ else go SPEC 1 wrd s fs
2221+ Skip s -> return $ Skip (SplitOnSeqWordInit s)
21572222 Stop -> return Stop
21582223
21592224 where
21602225
2161− mask :: Word
2162− mask = (1 `shiftL` (elemBits * patLen)) - 1
2163−
2164− addToWord wrd a = (wrd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
2165−
2166− patWord :: Word
2167− patWord = mask .&. A.foldl' addToWord 0 patArr
2168−
2169− go0 !_ !idx wrd st !acc = do
2226+ {-# INLINE go #-}
2227+ go !_ !idx !wrd !st !fs = do
21702228 res <- step (adaptState gst) st
21712229 case res of
21722230 Yield x s -> do
2173− let wrd' = addToWord wrd x
2174− acc' <- if withSep then fstep acc x else return acc
2175− if idx == maxIndex
2231+ let wrd1 = addToWord wrd x
2232+ if withSep
21762233 then do
2177− if wrd' .&. mask == patWord
2234+ fs1 <- fstep fs x
2235+ if idx == maxIndex
21782236 then do
2179− r <- done acc'
2180− return $ Yield r (GO_SHORT_PAT s)
2181− else go1 SPEC wrd' s acc'
2182− else go0 SPEC (idx + 1) wrd' s acc'
2183− Skip s -> go0 SPEC idx wrd s acc
2184− Stop -> do
2185− if (idx == maxIndex) && (wrd .&. mask == patWord)
2186− then return Stop
2237+ if wrd1 .&. wordMask == wordPat
2238+ then do
2239+ r <- done fs
2240+ let next = SplitOnSeqWordInit s
2241+ skip $ SplitOnSeqYield r next
2242+ else skip $ SplitOnSeqWordLoop wrd1 s fs1
2243+ else go SPEC (idx + 1) wrd1 s fs1
21872244 else do
2188− acc' <- if idx /= 0 && not withSep
2189− then go2 wrd idx acc
2190− else return acc
2191− done acc' >>= \r -> return $ Yield r GO_DONE1
2245+ if idx == maxIndex
2246+ then do
2247+ if wrd1 .&. wordMask == wordPat
2248+ then do
2249+ r <- done fs
2250+ let next = SplitOnSeqWordInit s
2251+ skip $ SplitOnSeqYield r next
2252+ else skip $ SplitOnSeqWordLoop wrd1 s fs
2253+ else go SPEC (idx + 1) wrd1 s fs
2254+ Skip s -> go SPEC idx wrd s fs
2255+ Stop -> skip $ SplitOnSeqWordDone idx fs wrd
2256+
2257+ stepOuter gst (SplitOnSeqWordLoop wrd0 st0 fs0) =
2258+ go SPEC wrd0 st0 fs0
21922259
2193− {-# INLINE go1 #-}
2194− go1 !_ wrd st !acc = do
2260+ where
2261+
2262+ {-# INLINE go #-}
2263+ go !_ !wrd !st !fs = do
21952264 res <- step (adaptState gst) st
21962265 case res of
21972266 Yield x s -> do
2198− let wrd' = addToWord wrd x
2199− old = (mask .&. wrd) `shiftR` (elemBits * (patLen - 1))
2200− acc' <- if withSep
2201− then fstep acc x
2202− else fstep acc (toEnum $ fromIntegral old)
2203− if wrd' .&. mask == patWord
2204− then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
2205− else go1 SPEC wrd' s acc'
2206− Skip s -> go1 SPEC wrd s acc
2267+ let wrd1 = addToWord wrd x
2268+ old = (wordMask .&. wrd)
2269+ `shiftR` (elemBits * (patLen - 1))
2270+ if withSep
2271+ then do
2272+ fs1 <- fstep fs x
2273+ if wrd1 .&. wordMask == wordPat
2274+ then do
2275+ r <- done fs1
2276+ let next = SplitOnSeqWordInit s
2277+ skip $ SplitOnSeqYield r next
2278+ else go SPEC wrd1 s fs1
2279+ else do
2280+ fs1 <- fstep fs (toEnum $ fromIntegral old)
2281+ if wrd1 .&. wordMask == wordPat
2282+ then do
2283+ r <- done fs1
2284+ let next = SplitOnSeqWordInit s
2285+ skip $ SplitOnSeqYield r next
2286+ else go SPEC wrd1 s fs1
2287+ Skip s -> go SPEC wrd s fs
22072288 Stop ->
2208− -- If the last sequence is a separator do not issue a blank
2209− -- segment.
2210− if wrd .&. mask == patWord
2289+ if wrd .&. wordMask == wordPat
22112290 then return Stop
2212− else do
2213− acc' <- if withSep
2214− then return acc
2215− else go2 wrd patLen acc
2216− done acc' >>= \r -> return $ Yield r GO_DONE1
2217−
2218− go2 !wrd !n !acc | n > 0 = do
2219− let old = (mask .&. wrd) `shiftR` (elemBits * (n - 1))
2220− fstep acc (toEnum $ fromIntegral old) >>= go2 wrd (n - 1)
2221− go2 _ _ acc = return acc
2222−
2223− stepOuter gst (GO_KARP_RABIN stt rb rhead) = do
2224− let idx = 0
2225− res <- step (adaptState gst) stt
2291+ else
2292+ if withSep
2293+ then do
2294+ r <- done fs
2295+ skip $ SplitOnSeqYield r SplitOnSeqDone
2296+ else skip $ SplitOnSeqWordDone patLen fs wrd
2297+
2298+ -------------------------------
2299+ -- General Pattern - Karp Rabin
2300+ -------------------------------
2301+
2302+ stepOuter gst (SplitOnSeqKRInit idx0 st0 rb rh0) = do
2303+ res <- step (adaptState gst) st0
22262304 case res of
22272305 Yield x s -> do
2228− acc <- initial
2229− acc' <- if withSep then fstep acc x else return acc
2230− rh' <- liftIO (RB.unsafeInsert rb rhead x)
2231− if idx == maxIndex
2306+ rh1 <- liftIO $ RB.unsafeInsert rb rh0 x
2307+ fs <- initial
2308+ if withSep
22322309 then do
2233− let fold = RB.unsafeFoldRing (RB.ringBound rb)
2234− let !ringHash = fold addCksum 0 rb
2235− if ringHash == patHash
2236− then go2 SPEC ringHash rh' s acc'
2237− else go0 SPEC (idx + 1) rh' s acc'
2238− else go0 SPEC (idx + 1) rh' s acc'
2239− Skip s -> return $ Skip (GO_KARP_RABIN s rb rhead)
2310+ fs1 <- fstep fs x
2311+ go SPEC 1 rh1 s fs1
2312+ else go SPEC 1 rh1 s fs
2313+ Skip s -> skip $ SplitOnSeqKRInit idx0 s rb rh0
22402314 Stop -> return Stop
22412315
22422316 where
22432317
2244− k = 2891336453 :: Word32
2245− coeff = k ^ patLen
2246− addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
2247− deltaCksum cksum old new =
2248− addCksum cksum new - coeff * fromIntegral (fromEnum old)
2249−
2250− -- XXX shall we use a random starting hash or 1 instead of 0?
2251− patHash = A.foldl' addCksum 0 patArr
2252−
2253− -- rh == ringHead
2254− go0 !_ !idx !rh st !acc = do
2318+ go !_ !idx !rh st !fs = do
22552319 res <- step (adaptState gst) st
22562320 case res of
22572321 Yield x s -> do
2258− acc' <- if withSep then fstep acc x else return acc
2259− rh' <- liftIO (RB.unsafeInsert rb rh x)
2260− if idx == maxIndex
2322+ rh1 <- liftIO (RB.unsafeInsert rb rh x)
2323+ if withSep
22612324 then do
2262− let fold = RB.unsafeFoldRing (RB.ringBound rb)
2263− let !ringHash = fold addCksum 0 rb
2264− if ringHash == patHash
2265− then go2 SPEC ringHash rh' s acc'
2266− else go1 SPEC ringHash rh' s acc'
2267− else go0 SPEC (idx + 1) rh' s acc'
2268− Skip s -> go0 SPEC idx rh s acc
2325+ fs1 <- fstep fs x
2326+ if idx == maxIndex
2327+ then do
2328+ let fold = RB.unsafeFoldRing (RB.ringBound rb)
2329+ let !ringHash = fold addCksum 0 rb
2330+ if ringHash == patHash
2331+ then skip $ SplitOnSeqKRCheck fs1 s rb rh1
2332+ else skip $ SplitOnSeqKRLoop fs1 s rb rh1 ringHash
2333+ else go SPEC (idx + 1) rh1 s fs1
2334+ else
2335+ if idx == maxIndex
2336+ then do
2337+ let fold = RB.unsafeFoldRing (RB.ringBound rb)
2338+ let !ringHash = fold addCksum 0 rb
2339+ if ringHash == patHash
2340+ then skip $ SplitOnSeqKRCheck fs s rb rh1
2341+ else skip $ SplitOnSeqKRLoop fs s rb rh1 ringHash
2342+ else go SPEC (idx + 1) rh1 s fs
2343+ Skip s -> go SPEC idx rh s fs
22692344 Stop -> do
22702345 -- do not issue a blank segment when we end at pattern
22712346 if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
22722347 then return Stop
2273− else do
2274− !acc' <- if idx /= 0 && not withSep
2275− then RB.unsafeFoldRingM rh fstep acc rb
2276− else return acc
2277− done acc' >>= \r -> return $ Yield r GO_DONE1
2278−
2279− -- XXX Theoretically this code can do 4 times faster if GHC generates
2280− -- optimal code. If we use just "(cksum' == patHash)" condition it goes
2281− -- 4x faster, as soon as we add the "RB.unsafeEqArray rb v" condition
2282− -- the generated code changes drastically and becomes 4x slower. Need
2283− -- to investigate what is going on with GHC.
2284− {-# INLINE go1 #-}
2285− go1 !_ !cksum !rh st !acc = do
2348+ else
2349+ if withSep
2350+ then do
2351+ r <- done fs
2352+ skip $ SplitOnSeqYield r SplitOnSeqDone
2353+ else skip $ SplitOnSeqKRDone idx fs rb (RB.startOf rb)
2354+
2355+ -- XXX The recursive "go" is more efficient than the state based recursion
2356+ -- code commented out below. Perhaps its more efficient because of
2357+ -- factoring out "rb" outside the loop.
2358+ --
2359+ stepOuter gst (SplitOnSeqKRLoop fs0 st0 rb rh0 cksum0) =
2360+ go SPEC fs0 st0 rh0 cksum0
2361+
2362+ where
2363+
2364+ go !_ !fs !st !rh !cksum = do
22862365 res <- step (adaptState gst) st
22872366 case res of
22882367 Yield x s -> do
22892368 old <- liftIO $ peek rh
2290− let cksum' = deltaCksum cksum old x
2291− acc' <- if withSep
2292− then fstep acc x
2293− else fstep acc old
2294−
2295− if (cksum' == patHash)
2369+ rh1 <- liftIO (RB.unsafeInsert rb rh x)
2370+ let cksum1 = deltaCksum cksum old x
2371+ if withSep
22962372 then do
2297− rh' <- liftIO (RB.unsafeInsert rb rh x)
2298− go2 SPEC cksum' rh' s acc'
2373+ fs1 <- fstep fs x
2374+ if (cksum1 == patHash)
2375+ then skip $ SplitOnSeqKRCheck fs1 s rb rh1
2376+ else go SPEC fs1 s rh1 cksum1
22992377 else do
2300− rh' <- liftIO (RB.unsafeInsert rb rh x)
2301− go1 SPEC cksum' rh' s acc'
2302− Skip s -> go1 SPEC cksum rh s acc
2303− Stop -> do
2378+ fs1 <- fstep fs old
2379+ if (cksum1 == patHash)
2380+ then skip $ SplitOnSeqKRCheck fs1 s rb rh1
2381+ else go SPEC fs1 s rh1 cksum1
2382+ Skip s -> go SPEC fs s rh cksum
2383+ Stop ->
23042384 if RB.unsafeEqArray rb rh patArr
23052385 then return Stop
2306− else do
2307− acc' <- if withSep
2308− then return acc
2309− else RB.unsafeFoldRingFullM rh fstep acc rb
2310− done acc' >>= \r -> return $ Yield r GO_DONE1
2311−
2312− go2 !_ !cksum' !rh' s !acc' = do
2313− if RB.unsafeEqArray rb rh' patArr
2314− then do
2315− r <- done acc'
2316− return $ Yield r (GO_KARP_RABIN s rb rhead)
2317− else go1 SPEC cksum' rh' s acc'
2318−
2319− stepOuter gst (GO_EMPTY_PAT1 st) = do
2320− res <- step (adaptState gst) st
2321− case res of
2322− Yield x s -> do
2323− acc <- initial
2324− acc' <- fstep acc x
2325− done acc' >>= \r -> return $ Yield r (GO_EMPTY_PAT1 s)
2326− Skip s -> return $ Skip (GO_EMPTY_PAT1 s)
2327− Stop -> return Stop
2386+ else
2387+ if withSep
2388+ then do
2389+ r <- done fs
2390+ skip $ SplitOnSeqYield r SplitOnSeqDone
2391+ else skip $ SplitOnSeqKRDone patLen fs rb rh
2392+
2393+ stepOuter _ (SplitOnSeqKRCheck fs st rb rh) = do
2394+ if RB.unsafeEqArray rb rh patArr
2395+ then do
2396+ r <- done fs
2397+ let next = SplitOnSeqKRInit 0 st rb (RB.startOf rb)
2398+ skip $ SplitOnSeqYield r next
2399+ else skip $ SplitOnSeqKRLoop fs st rb rh patHash
23282400
2329− stepOuter _ GO_DONE1 = return Stop
2401+ stepOuter _ (SplitOnSeqKRDone 0 fs _ _) = do
2402+ r <- done fs
2403+ skip $ SplitOnSeqYield r SplitOnSeqDone
2404+ stepOuter _ (SplitOnSeqKRDone n fs rb rh) = do
2405+ old <- liftIO $ peek rh
2406+ let rh1 = RB.advance rb rh
2407+ fs1 <- fstep fs old
2408+ skip $ SplitOnSeqKRDone (n - 1) fs1 rb rh1
23302409
23312410data SplitState s arr
23322411 = SplitInitial s