From 287d9e5c4fc50bcca2474b9783148181d7ede872 Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Mon, 6 Apr 2026 23:35:05 +0200 Subject: Log watching --- src/ImmutGrowVector.hs | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/ImmutGrowVector.hs (limited to 'src/ImmutGrowVector.hs') diff --git a/src/ImmutGrowVector.hs b/src/ImmutGrowVector.hs new file mode 100644 index 0000000..d36209d --- /dev/null +++ b/src/ImmutGrowVector.hs @@ -0,0 +1,43 @@ +module ImmutGrowVector where + +import Foreign.Storable +import Data.Vector.Storable qualified as VS + + +-- | Acts like an immutable storable vector, except that it's split in a long +-- prefix and a short suffix so that modifications at the end are cheap. If the +-- suffix gets longer (by appending elements), the suffix elements are promoted +-- to prefix elements once in a while, resulting in a big copy at those times. +data ImmutGrowVector a = ImmutGrowVector (VS.Vector a) (VS.Vector a) + deriving (Show) + +empty :: Storable a => ImmutGrowVector a +empty = ImmutGrowVector VS.empty VS.empty + +fromListN :: Storable a => Int -> [a] -> ImmutGrowVector a +fromListN n l + | n > 2 = + let (l1, l2) = splitAt (n - 2) l + in ImmutGrowVector (VS.fromListN (n - 2) l1) (VS.fromListN 2 l2) + | otherwise = + ImmutGrowVector VS.empty (VS.fromListN n l) + +(!) :: Storable a => ImmutGrowVector a -> Int -> a +ImmutGrowVector prefix suffix ! i + | i < VS.length prefix = prefix VS.! i + | otherwise = suffix VS.! (i - VS.length prefix) + +length :: Storable a => ImmutGrowVector a -> Int +length (ImmutGrowVector prefix suffix) = VS.length prefix + VS.length suffix + +set :: Storable a => ImmutGrowVector a -> Int -> a -> ImmutGrowVector a +set (ImmutGrowVector prefix suffix) idx value + | idx < VS.length prefix = error "ImmutGrowVector: mutation in slow part" + | otherwise = ImmutGrowVector prefix (suffix VS.// [(idx - VS.length prefix, value)]) + +append :: Storable a => ImmutGrowVector a -> a -> ImmutGrowVector a +append (ImmutGrowVector prefix suffix) value + | VS.length suffix < 8 = ImmutGrowVector prefix (suffix `VS.snoc` value) + | otherwise = + let n = VS.length suffix + in ImmutGrowVector (prefix <> VS.take (n - 1) suffix) (VS.drop (n - 1) suffix `VS.snoc` value) -- cgit v1.3