packages feed

vector-circular 0.1.1 → 0.1.2

raw patch · 4 files changed

+3556/−555 lines, 4 filesdep +doctestdep ~basenew-uploader

Dependencies added: doctest

Dependency ranges changed: base

Files

src/Data/Vector/Circular.hs view
@@ -9,557 +9,1741 @@   , ScopedTypeVariables   , TemplateHaskell   , TypeApplications-#-}--module Data.Vector.Circular-  ( -- * Types-    CircularVector(..)--    -- * Construction-  , singleton-  , toVector-  , toNonEmptyVector-  , fromVector-  , unsafeFromVector-  , fromList-  , fromListN-  , unsafeFromList-  , unsafeFromListN-  , vec--    -- * Rotation-  , rotateLeft-  , rotateRight--    -- * Comparisons-  , equivalent-  , canonise-  , leastRotation--    -- * Folds-  , Data.Vector.Circular.foldMap-  , Data.Vector.Circular.foldMap'-  , Data.Vector.Circular.foldr-  , Data.Vector.Circular.foldl-  , Data.Vector.Circular.foldr'-  , Data.Vector.Circular.foldl'-  , Data.Vector.Circular.foldr1-  , Data.Vector.Circular.foldl1-  , Data.Vector.Circular.foldMap1-  , Data.Vector.Circular.foldMap1'-  , Data.Vector.Circular.toNonEmpty--    -- * Specialized folds-  , Data.Vector.Circular.all-  , Data.Vector.Circular.any-  , Data.Vector.Circular.and-  , Data.Vector.Circular.or-  , Data.Vector.Circular.sum-  , Data.Vector.Circular.product-  , Data.Vector.Circular.maximum-  , Data.Vector.Circular.maximumBy-  , Data.Vector.Circular.minimum-  , Data.Vector.Circular.minimumBy-  , rotateToMinimumBy-  , rotateToMaximumBy--    -- * Indexing-  , index-  , head-  , last--    -- * Zipping-  , Data.Vector.Circular.zipWith-  , Data.Vector.Circular.zipWith3-  , Data.Vector.Circular.zip-  , Data.Vector.Circular.zip3--    -- * Permutations-  , Data.Vector.Circular.reverse-  ) where--import Control.Monad (when, forM_)-import Control.Monad.ST (ST, runST)-import Control.DeepSeq-#if MIN_VERSION_base(4,13,0)-import Data.Foldable (foldMap')-#endif /* MIN_VERSION_base(4,13,0) */-import Data.List.NonEmpty (NonEmpty)-import Data.Primitive.MutVar-import Data.Semigroup.Foldable.Class (Foldable1)-import Data.Monoid (All(..))-import Data.Vector (Vector)-import Data.Vector.NonEmpty (NonEmptyVector)-import GHC.Base (modInt)-import GHC.Generics (Generic)-import Prelude hiding (head, length, last)-import Language.Haskell.TH.Syntax-import qualified Data.Foldable as Foldable-import qualified Data.Semigroup.Foldable.Class as Foldable1-import qualified Data.Vector as Vector-import qualified Data.Vector.Mutable as MVector-import qualified Data.Vector.NonEmpty as NonEmpty-import qualified Prelude---- | A circular, immutable vector. This type is equivalent to---   @'Data.List.cycle' xs@ for some finite, nonempty @xs@, but---   with /O(1)/ access and /O(1)/ rotations. Indexing---   into this type is always total.-data CircularVector a = CircularVector-  { vector :: {-# UNPACK #-} !(NonEmptyVector a)-  , rotation :: {-# UNPACK #-} !Int-  }-  deriving stock-    ( Functor -- ^ @since 0.1-    , Generic -- ^ @since 0.1.1-    , Ord     -- ^ @since 0.1-    , Read    -- ^ @since 0.1-    , Show    -- ^ @since 0.1-    )-  deriving anyclass-    ( NFData -- ^ @since 0.1.1-    )---- | @since 0.1.1-instance Traversable CircularVector where-  traverse :: (Applicative f) => (a -> f b) -> CircularVector a -> f (CircularVector b)-  traverse f (CircularVector v rot) =-    CircularVector <$> traverse f v <*> pure rot---- | @since 0.1-instance Eq a => Eq (CircularVector a) where-  (==) :: CircularVector a -> CircularVector a -> Bool-  c0@(CircularVector x rx) == c1@(CircularVector y ry)-    | NonEmpty.length x /= NonEmpty.length y = False-    | rx == ry = x == y-    | otherwise = getAll $ flip Prelude.foldMap [0..NonEmpty.length x-1] $ \i -> All (index c0 i == index c1 i)---- | The 'Semigroup' @('<>')@ operation behaves by un-rolling---   the two vectors so that their rotation is 0, concatenating---   them, returning a new vector with a 0-rotation.------   @since 0.1-instance Semigroup (CircularVector a) where-  (<>) :: CircularVector a -> CircularVector a -> CircularVector a-  lhs <> rhs = CircularVector v 0-    where-      szLhs = length lhs-      szRhs = length rhs-      sz = szLhs + szRhs-      v = NonEmpty.unsafeFromVector-            $ Vector.generate sz-            $ \ix -> if ix < szLhs-                then index lhs ix-                else index rhs (ix - szLhs)-  {-# inline (<>) #-}---- | @since 0.1-instance Foldable CircularVector where-  foldMap :: Monoid m => (a -> m) -> CircularVector a -> m-  foldMap = Data.Vector.Circular.foldMap-  {-# inline foldMap #-}--#if MIN_VERSION_base(4,13,0)-  foldMap' :: Monoid m => (a -> m) -> CircularVector a -> m-  foldMap' = Data.Vector.Circular.foldMap'-  {-# inline foldMap' #-}-#endif /* MIN_VERSION_base(4,13,0) */--  null :: CircularVector a -> Bool-  null _ = False -- nonempty structure is always not null-  {-# inline null #-}--  length :: CircularVector a -> Int-  length = Data.Vector.Circular.length-  {-# inline length #-}---- | @since 0.1-instance Foldable1 CircularVector where-  foldMap1 :: Semigroup m => (a -> m) -> CircularVector a -> m-  foldMap1 = Data.Vector.Circular.foldMap1-  {-# inline foldMap1 #-}---- | @since 0.1-instance Lift a => Lift (CircularVector a) where-  lift c = do-    v <- [|NonEmpty.toVector (vector c)|]-    r <- [|rotation c|]-    pure $ ConE ''CircularVector-      `AppE` (VarE 'NonEmpty.unsafeFromVector `AppE` v)-      `AppE` r-#if MIN_VERSION_template_haskell(2,16,0)-  liftTyped = unsafeTExpCoerce . lift-#endif /* MIN_VERSION_template_haskell(2,16,0) */---- | Get the length of a 'CircularVector'.------   @since 0.1-length :: CircularVector a -> Int-length (CircularVector v _) = NonEmpty.length v-{-# inline length #-}---- | Lazily-accumulating monoidal fold over a 'CircularVector'.---   @since 0.1-foldMap :: Monoid m => (a -> m) -> CircularVector a -> m-foldMap f = \v ->-  let len = Data.Vector.Circular.length v-      go !ix-        | ix < len = f (index v ix) <> go (ix + 1)-        | otherwise = mempty-  in go 0-{-# inline foldMap #-}---- | Strictly-accumulating monoidal fold over a 'CircularVector'.------   @since 0.1-foldMap' :: Monoid m => (a -> m) -> CircularVector a -> m-foldMap' f = \v ->-  let len = Data.Vector.Circular.length v-      go !ix !acc-        | ix < len = go (ix + 1) (acc <> f (index v ix))-        | otherwise = acc-  in go 0 mempty-{-# inline foldMap' #-}---- | @since 0.1-foldr :: (a -> b -> b) -> b -> CircularVector a -> b-foldr = Foldable.foldr---- | @since 0.1-foldl :: (b -> a -> b) -> b -> CircularVector a -> b-foldl = Foldable.foldl---- | @since 0.1-foldr' :: (a -> b -> b) -> b -> CircularVector a -> b-foldr' = Foldable.foldr'---- | @since 0.1-foldl' :: (b -> a -> b) -> b -> CircularVector a -> b-foldl' = Foldable.foldl'---- | @since 0.1-foldr1 :: (a -> a -> a) -> CircularVector a -> a-foldr1 = Foldable.foldr1---- | @since 0.1-foldl1 :: (a -> a -> a) -> CircularVector a -> a-foldl1 = Foldable.foldl1---- | @since 0.1-toNonEmpty :: CircularVector a -> NonEmpty a-toNonEmpty = Foldable1.toNonEmpty---- | Lazily-accumulating semigroupoidal fold over---   a 'CircularVector'.------   @since 0.1-foldMap1 :: Semigroup m => (a -> m) -> CircularVector a -> m-foldMap1 f = \v ->-  let len = Data.Vector.Circular.length v-      go !ix-        | ix < len-1 = f (index v ix) <> go (ix + 1)-        | otherwise  = f (last v)-  in go 0-{-# inline foldMap1 #-}---- | Strictly-accumulating semigroupoidal fold over---   a 'CircularVector'.------   @since 0.1-foldMap1' :: Semigroup m => (a -> m) -> CircularVector a -> m-foldMap1' f = \v ->-  let len = Data.Vector.Circular.length v-      go !ix !acc-        | ix < len = go (ix + 1) (acc <> f (index v ix))-        | otherwise = acc-  in go 1 (f (head v))-{-# inline foldMap1' #-}---- | Construct a 'Vector' from a 'CircularVector'.------   @since 0.1-toVector :: CircularVector a -> Vector a-toVector v = Vector.generate (length v) (index v)---- | Construct a 'NonEmptyVector' from a 'CircularVector'.------   @since 0.1.1-toNonEmptyVector :: CircularVector a -> NonEmptyVector a-toNonEmptyVector v = NonEmpty.generate1 (length v) (index v)---- | Construct a 'CircularVector' from a 'NonEmptyVector'.------   @since 0.1-fromVector :: NonEmptyVector a -> CircularVector a-fromVector v = CircularVector v 0-{-# inline fromVector #-}---- | Construct a 'CircularVector' from a 'Vector'.------   Calls @'error'@ if the input vector is empty.------   @since 0.1-unsafeFromVector :: Vector a -> CircularVector a-unsafeFromVector = fromVector . NonEmpty.unsafeFromVector---- | Construct a 'CircularVector' from a list.------   @since 0.1-fromList :: [a] -> Maybe (CircularVector a)-fromList xs = fromListN (Prelude.length xs) xs-{-# inline fromList #-}---- | Construct a 'CircularVector' from a list with a size hint.------   @since 0.1-fromListN :: Int -> [a] -> Maybe (CircularVector a)-fromListN n xs = fromVector <$> (NonEmpty.fromListN n xs)-{-# inline fromListN #-}---- | Construct a 'CircularVector' from a list.------   Calls @'error'@ if the input list is empty.------   @since 0.1-unsafeFromList :: [a] -> CircularVector a-unsafeFromList xs = unsafeFromListN (Prelude.length xs) xs---- | Construct a 'CircularVector' from a list with a size hint.------   Calls @'error'@ if the input list is empty, or---   if the size hint is @'<=' 0@.------    @since 0.1-unsafeFromListN :: Int -> [a] -> CircularVector a-unsafeFromListN n xs-  | n <= 0 = error "Data.Vector.Circular.unsafeFromListN: invalid length!"-  | otherwise = unsafeFromVector (Vector.fromListN n xs)---- | Construct a singleton 'CircularVector.------   @since 0.1-singleton :: a -> CircularVector a-singleton = fromVector . NonEmpty.singleton-{-# inline singleton #-}---- | Index into a 'CircularVector'. This is always total.------   @since 0.1-index :: CircularVector a -> Int -> a-index (CircularVector v r) = \ !ix ->-  let len = NonEmpty.length v-  in NonEmpty.unsafeIndex v (unsafeMod (ix + r) len)-{-# inline index #-}---- | Get the first element of a 'CircularVector'. This is always total.------   @since 0.1-head :: CircularVector a -> a-head v = index v 0-{-# inline head #-}---- | Get the last element of a 'CircularVector'. This is always total.------   @since 0.1-last :: CircularVector a -> a-last v = index v (Data.Vector.Circular.length v - 1)-{-# inline last #-}---- | Rotate the vector to left by @n@ number of elements.------   /Note/: Right rotations start to break down due to---   arithmetic overflow when the size of the input vector is---   @'>' 'maxBound' @'Int'@------   @since 0.1-rotateRight :: Int -> CircularVector a -> CircularVector a-rotateRight r' (CircularVector v r) = CircularVector v h-  where-    len = NonEmpty.length v-    h = unsafeMod (r + unsafeMod r' len) len-{-# inline rotateRight #-}---- | Rotate the vector to the left by @n@ number of elements.------   /Note/: Left rotations start to break down due to---   arithmetic underflow when the size of the input vector is---   @'>' 'maxBound' @'Int'@------   @since 0.1-rotateLeft :: Int -> CircularVector a -> CircularVector a-rotateLeft r' (CircularVector v r) = CircularVector v h-  where-    len = NonEmpty.length v-    h = unsafeMod (r - unsafeMod r' len) len-{-# inline rotateLeft #-}---- | Construct a 'CircularVector' at compile-time using---   typed Template Haskell.------   @since 0.1-vec :: Lift a => [a] -> Q (TExp (CircularVector a))-vec [] = fail "Cannot create an empty CircularVector!"-vec xs =-#if MIN_VERSION_template_haskell(2,16,0)-  liftTyped (unsafeFromList xs)-#else-  unsafeTExpCoerce [|unsafeFromList xs|]-#endif /* MIN_VERSION_template_haskell(2,16,0) */---- | @since 0.1-equivalent :: Ord a => CircularVector a -> CircularVector a -> Bool-equivalent x y = vector (canonise x) == vector (canonise y)---- | @since 0.1-canonise :: Ord a => CircularVector a -> CircularVector a-canonise (CircularVector v r) = CircularVector v' (r - lr)-  where-    lr = leastRotation (NonEmpty.toVector v)-    v' = toNonEmptyVector (rotateRight lr (CircularVector v 0))---- | @since 0.1-leastRotation :: forall a. (Ord a) => Vector a -> Int-leastRotation v = runST go-  where-    go :: forall s. ST s Int-    go = do-      let s = v <> v-      let len = Vector.length s-      f <- MVector.replicate @_ @Int len (-1)-      kVar <- newMutVar @_ @Int 0-      forM_ [1..len-1] $ \j -> do-        sj <- Vector.indexM s j-        i0 <- readMutVar kVar >>= \k -> MVector.read f (j - k - 1)-        let loop i = do-              a <- readMutVar kVar >>= \k -> Vector.indexM s (k + i + 1)-              if (i /= (-1) && sj /= a)-                then do-                  when (sj < a) (writeMutVar kVar (j - i - 1))-                  loop =<< MVector.read f i-                else pure i-        i <- loop i0-        a <- readMutVar kVar >>= \k -> Vector.indexM s (k + i + 1)-        if sj /= a-          then do-            readMutVar kVar >>= \k -> when (sj < (s Vector.! k)) (writeMutVar kVar j)-            readMutVar kVar >>= \k -> MVector.write f (j - k) (-1)-          else do-            readMutVar kVar >>= \k -> MVector.write f (j - k) (i + 1)-      readMutVar kVar---- only safe if second argument is nonzero.--- used internally for modulus operations with length.-unsafeMod :: Int -> Int -> Int-unsafeMod = GHC.Base.modInt-{-# inline unsafeMod #-}---- | /O(min(m,n))/ Zip two circular vectors with the given function.------   @since 0.1.1-zipWith :: (a -> b -> c) -> CircularVector a -> CircularVector b -> CircularVector c-zipWith f a b = fromVector $ NonEmpty.zipWith f (toNonEmptyVector a) (toNonEmptyVector b)---- | Zip three circular vectors with the given function.------   @since 0.1.1-zipWith3 :: (a -> b -> c -> d) -> CircularVector a -> CircularVector b -> CircularVector c-  -> CircularVector d-zipWith3 f a b c = fromVector $-  NonEmpty.zipWith3 f (toNonEmptyVector a) (toNonEmptyVector b) (toNonEmptyVector c)---- | /O(min(n,m))/ Elementwise pairing of circular vector elements.---   This is a special case of 'zipWith' where the function argument is '(,)'------   @since 0.1.1-zip :: CircularVector a -> CircularVector b -> CircularVector (a,b)-zip a b = fromVector $ NonEmpty.zip (toNonEmptyVector a) (toNonEmptyVector b)---- | Zip together three circular vectors.------   @since 0.1.1-zip3 :: CircularVector a -> CircularVector b -> CircularVector c -> CircularVector (a,b,c)-zip3 a b c = fromVector $ NonEmpty.zip3 (toNonEmptyVector a) (toNonEmptyVector b) (toNonEmptyVector c)---- | /O(n)/ Reverse a circular vector.------   @since 0.1.1-reverse :: CircularVector a -> CircularVector a-reverse = fromVector . NonEmpty.reverse . toNonEmptyVector---- | /O(n)/ Rotate to the minimum element of the circular vector according to the---   given comparison function.------   @since 0.1.1-rotateToMinimumBy :: (a -> a -> Ordering) -> CircularVector a -> CircularVector a-rotateToMinimumBy f (CircularVector v _rot) =-  CircularVector v (NonEmpty.minIndexBy f v)---- | /O(n)/ Rotate to the maximum element of the circular vector according to the---   given comparison function.------   @since 0.1.1-rotateToMaximumBy :: (a -> a -> Ordering) -> CircularVector a -> CircularVector a-rotateToMaximumBy f (CircularVector v _rot) =-  CircularVector v (NonEmpty.maxIndexBy f v)---- | /O(n)/ Check if all elements satisfy the predicate.------   @since 0.1.1-all :: (a -> Bool) -> CircularVector a -> Bool-all f = NonEmpty.all f . vector---- | /O(n)/ Check if any element satisfies the predicate.------   @since 0.1.1-any :: (a -> Bool) -> CircularVector a -> Bool-any f = NonEmpty.any f . vector---- | /O(n)/ Check if all elements are True.------   @since 0.1.1-and :: CircularVector Bool -> Bool-and = NonEmpty.and . vector---- | /O(n)/ Check if any element is True.------   @since 0.1.1-or :: CircularVector Bool -> Bool-or = NonEmpty.or . vector---- | /O(n)/ Compute the sum of the elements.------   @since 0.1.1-sum :: Num a => CircularVector a -> a-sum = NonEmpty.sum . vector---- | /O(n)/ Compute the product of the elements.------   @since 0.1.1-product :: Num a => CircularVector a -> a-product = NonEmpty.sum . vector---- | /O(n)/ Yield the maximum element of the circular vector.------   @since 0.1.1-maximum :: Ord a => CircularVector a -> a-maximum = NonEmpty.maximum . vector---- | /O(n)/ Yield the maximum element of a circular vector according to the---   given comparison function.------   @since 0.1.1-maximumBy :: (a -> a -> Ordering) -> CircularVector a -> a-maximumBy f = NonEmpty.maximumBy f . vector---- | /O(n)/ Yield the minimum element of the circular vector.------   @since 0.1.1-minimum :: Ord a => CircularVector a -> a-minimum = NonEmpty.minimum . vector---- | /O(n)/ Yield the minimum element of a circular vector according to the---   given comparison function.------   @since 0.1.1-minimumBy :: (a -> a -> Ordering) -> CircularVector a -> a-minimumBy f = NonEmpty.minimumBy f . vector+  , RankNTypes+#-}++module Data.Vector.Circular+  ( -- * Types+    CircularVector(..)++    -- * Construction+    -- ** Initialization+  , singleton+  , replicate+  , replicate1+  , generate+  , generate1+  , iterateN+  , iterateN1+    -- ** Monad Initialization+  , replicateM+  , replicate1M+  , generateM+  , generate1M+  , iterateNM+  , iterateN1M+  , create+  , unsafeCreate+  , createT+  , unsafeCreateT+    -- ** Unfolding+  , unfoldr+  , unfoldr1+  , unfoldrN+  , unfoldr1N+  , unfoldrM+  , unfoldr1M+  , unfoldrNM+  , unfoldr1NM+  , constructN+  , constructrN+    -- ** Enumeration+  , enumFromN+  , enumFromN1+  , enumFromStepN+  , enumFromStepN1+  , enumFromTo+  , enumFromThenTo+    -- ** Concatenation+  , cons+  , consV+  , snoc+  , snocV+  , (Data.Vector.Circular.++)+  , concat+  , concat1+    -- ** Restricting memory usage+  , force++    -- ** Template Haskell+  , vec++    -- * Conversion+  , toVector+  , fromVector+  , fromVector'+  , unsafeFromVector+  , toNonEmptyVector+  , toList+  , fromList+  , fromListN+  , unsafeFromList+  , unsafeFromListN++    -- * Rotation+  , rotateLeft+  , rotateRight++    -- * Comparisons+  , equivalent+  , canonise+  , leastRotation++    -- * Folds+  , foldMap+  , foldMap'+  , foldr+  , foldl+  , foldr'+  , foldl'+  , foldr1+  , foldl1+  , foldMap1+  , foldMap1'+  , toNonEmpty++    -- * Specialized folds+  , all+  , any+  , and+  , or+  , sum+  , product+  , maximum+  , maximumBy+  , minimum+  , minimumBy+  , rotateToMinimumBy+  , rotateToMaximumBy++    -- * Elementwise operations+    -- ** Indexing+  , index+  , head+  , last++    -- ** Mapping+  , map+  , imap+  , concatMap++    -- ** Monadic mapping+  , mapM+  , imapM+  , mapM_+  , imapM_+  , forM+  , forM_++    -- ** Zipping+  , zipWith+  , zipWith3+  , zip+  , zip3++    -- ** Unzipping+  , unzip+  , unzip3++    -- ** Filtering+  , uniq+  , mapMaybe+  , imapMaybe+  , filter+  , ifilter+  , filterM+  , ifilterM+  , takeWhile+  , dropWhile++    -- * Partitioning+  , partition+  , unstablePartition+  , span+  , break++    -- * Searching+  , elem+  , notElem+  , find+  , findIndex+  , findIndices+  , elemIndex+  , elemIndices++    -- * Permutations+  , reverse+  , backpermute+  , unsafeBackpermute++    -- * Safe destructive updates+  , modify++    -- * Monadic Sequencing+  , sequence+  , sequence_+  ) where++import qualified Control.Monad (when, forM_)+import Control.Monad.ST (ST, runST)+import Control.DeepSeq+#if MIN_VERSION_base(4,13,0)+-- import Data.Foldable (foldMap')+#endif /* MIN_VERSION_base(4,13,0) */+import Data.List.NonEmpty (NonEmpty((:|)))+import Data.Primitive.MutVar ( newMutVar, readMutVar, writeMutVar )+import Data.Semigroup.Foldable.Class (Foldable1)+import Data.Monoid (All(..))+import Data.Vector (Vector)+import Data.Vector.NonEmpty (NonEmptyVector)+import Data.Functor.Classes+import Text.Read (readPrec)+import GHC.Base (modInt)+import GHC.Generics (Generic)+import Prelude hiding (head, length, last, map, concat, takeWhile+                      ,dropWhile, span, break, elem, notElem, reverse+                      ,mapM, mapM_, foldMap, foldr+                      ,foldl, foldr1, foldl1, all, any, and, or, sum+                      ,product, maximum, minimum, concatMap+                      ,zipWith, zipWith3, zip, zip3, replicate, enumFromTo+                      ,enumFromThenTo, (++))+import Language.Haskell.TH.Syntax+import qualified Data.Foldable as Foldable+import qualified Data.Semigroup.Foldable.Class as Foldable1+import qualified Data.Vector as Vector+import qualified Data.Vector.Mutable as MVector+import qualified Data.Vector.NonEmpty as NonEmpty+import qualified Prelude+++-- | A circular, immutable vector. This type is equivalent to+--   @'Data.List.cycle' xs@ for some finite, nonempty @xs@, but+--   with /O(1)/ access and /O(1)/ rotations. Indexing+--   into this type is always total.+data CircularVector a = CircularVector+  { vector :: {-# UNPACK #-} !(NonEmptyVector a)+  , rotation :: {-# UNPACK #-} !Int+  }+  deriving stock+    ( Functor -- ^ @since 0.1+    , Generic -- ^ @since 0.1.1+    , Ord     -- ^ @since 0.1+    , Read    -- ^ @since 0.1+    , Show    -- ^ @since 0.1+    )+  deriving anyclass+    ( NFData -- ^ @since 0.1.1+    )++-- | @since 0.1.1+instance Traversable CircularVector where+  traverse :: (Applicative f) => (a -> f b) -> CircularVector a -> f (CircularVector b)+  traverse f (CircularVector v rot) =+    CircularVector <$> traverse f v <*> pure rot++-- | @since 0.1+instance Eq a => Eq (CircularVector a) where+  (==) :: CircularVector a -> CircularVector a -> Bool+  (==) = liftEq (==)++-- | @since 0.1.2+instance Eq1 CircularVector where+  liftEq :: (a -> b -> Bool) -> CircularVector a -> CircularVector b -> Bool+  liftEq eq c0@(CircularVector x rx) c1@(CircularVector y ry)+    | NonEmpty.length x /= NonEmpty.length y = False+    | rx == ry = liftEq eq x y+    | otherwise = getAll $ flip Prelude.foldMap [0..NonEmpty.length x-1] $ \i ->+        All (index c0 i `eq` index c1 i)++-- | @since 0.1.2+instance Ord1 CircularVector where+  liftCompare :: (a -> b -> Ordering) -> CircularVector a -> CircularVector b -> Ordering+  liftCompare cmp (CircularVector x rx) (CircularVector y ry)+    = liftCompare cmp x y <> compare rx ry++-- | @since 0.1.2+instance Show1 CircularVector where+  liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> CircularVector a -> ShowS+  liftShowsPrec sp sl d (CircularVector x rx) =+    showsBinaryWith (liftShowsPrec sp sl) showsPrec "CircularVector" d x rx++-- | @since 0.1.2+instance Read1 CircularVector where+  liftReadPrec rp rl = readData $+    readBinaryWith (liftReadPrec rp rl) readPrec "CircularVector" CircularVector+  liftReadListPrec = liftReadListPrecDefault++-- | The 'Semigroup' @('<>')@ operation behaves by un-rolling+--   the two vectors so that their rotation is 0, concatenating+--   them, returning a new vector with a 0-rotation.+--+--   @since 0.1+instance Semigroup (CircularVector a) where+  (<>) :: CircularVector a -> CircularVector a -> CircularVector a+  lhs <> rhs = CircularVector v 0+    where+      szLhs = length lhs+      szRhs = length rhs+      sz = szLhs + szRhs+      v = NonEmpty.unsafeFromVector+            $ Vector.generate sz+            $ \ix -> if ix < szLhs+                then index lhs ix+                else index rhs (ix - szLhs)+  {-# inline (<>) #-}++-- | @since 0.1+instance Foldable CircularVector where+  foldMap :: Monoid m => (a -> m) -> CircularVector a -> m+  foldMap = Data.Vector.Circular.foldMap+  {-# inline foldMap #-}++#if MIN_VERSION_base(4,13,0)+  foldMap' :: Monoid m => (a -> m) -> CircularVector a -> m+  foldMap' = Data.Vector.Circular.foldMap'+  {-# inline foldMap' #-}+#endif /* MIN_VERSION_base(4,13,0) */++  null :: CircularVector a -> Bool+  null _ = False -- nonempty structure is always not null+  {-# inline null #-}++  length :: CircularVector a -> Int+  length = Data.Vector.Circular.length+  {-# inline length #-}++-- | @since 0.1+instance Foldable1 CircularVector where+  foldMap1 :: Semigroup m => (a -> m) -> CircularVector a -> m+  foldMap1 = Data.Vector.Circular.foldMap1+  {-# inline foldMap1 #-}++-- | @since 0.1+instance Lift a => Lift (CircularVector a) where+  lift c = do+    v <- [|NonEmpty.toVector (vector c)|]+    r <- [|rotation c|]+    pure $ ConE ''CircularVector+      `AppE` (VarE 'NonEmpty.unsafeFromVector `AppE` v)+      `AppE` r+#if MIN_VERSION_template_haskell(2,16,0)+  liftTyped = unsafeTExpCoerce . lift+#endif /* MIN_VERSION_template_haskell(2,16,0) */++-- | Get the length of a 'CircularVector'.+--+--   @since 0.1+length :: CircularVector a -> Int+length (CircularVector v _) = NonEmpty.length v+{-# inline length #-}++-- | Lazily-accumulating monoidal fold over a 'CircularVector'.+--   @since 0.1+foldMap :: Monoid m => (a -> m) -> CircularVector a -> m+foldMap f = \v ->+  let len = Data.Vector.Circular.length v+      go !ix+        | ix < len = f (index v ix) <> go (ix + 1)+        | otherwise = mempty+  in go 0+{-# inline foldMap #-}++-- | Strictly-accumulating monoidal fold over a 'CircularVector'.+--+--   @since 0.1+foldMap' :: Monoid m => (a -> m) -> CircularVector a -> m+foldMap' f = \v ->+  let len = Data.Vector.Circular.length v+      go !ix !acc+        | ix < len = go (ix + 1) (acc <> f (index v ix))+        | otherwise = acc+  in go 0 mempty+{-# inline foldMap' #-}++-- | @since 0.1+foldr :: (a -> b -> b) -> b -> CircularVector a -> b+foldr = Foldable.foldr++-- | @since 0.1+foldl :: (b -> a -> b) -> b -> CircularVector a -> b+foldl = Foldable.foldl++-- | @since 0.1+foldr' :: (a -> b -> b) -> b -> CircularVector a -> b+foldr' = Foldable.foldr'++-- | @since 0.1+foldl' :: (b -> a -> b) -> b -> CircularVector a -> b+foldl' = Foldable.foldl'++-- | @since 0.1+foldr1 :: (a -> a -> a) -> CircularVector a -> a+foldr1 = Foldable.foldr1++-- | @since 0.1+foldl1 :: (a -> a -> a) -> CircularVector a -> a+foldl1 = Foldable.foldl1++-- | @since 0.1+toNonEmpty :: CircularVector a -> NonEmpty a+toNonEmpty = Foldable1.toNonEmpty++-- | Lazily-accumulating semigroupoidal fold over+--   a 'CircularVector'.+--+--   @since 0.1+foldMap1 :: Semigroup m => (a -> m) -> CircularVector a -> m+foldMap1 f = \v ->+  let len = Data.Vector.Circular.length v+      go !ix+        | ix < len-1 = f (index v ix) <> go (ix + 1)+        | otherwise  = f (last v)+  in go 0+{-# inline foldMap1 #-}++-- | Strictly-accumulating semigroupoidal fold over+--   a 'CircularVector'.+--+--   @since 0.1+foldMap1' :: Semigroup m => (a -> m) -> CircularVector a -> m+foldMap1' f = \v ->+  let len = Data.Vector.Circular.length v+      go !ix !acc+        | ix < len = go (ix + 1) (acc <> f (index v ix))+        | otherwise = acc+  in go 1 (f (head v))+{-# inline foldMap1' #-}++-- | /O(n)/ Construct a 'Vector' from a 'CircularVector'.+--+--   @since 0.1+toVector :: CircularVector a -> Vector a+toVector v = Vector.generate (length v) (index v)++-- | /O(n)/ Construct a 'NonEmptyVector' from a 'CircularVector'.+--+--   @since 0.1.1+toNonEmptyVector :: CircularVector a -> NonEmptyVector a+toNonEmptyVector v = NonEmpty.generate1 (length v) (index v)++-- | /O(1)/ Construct a 'CircularVector' from a 'NonEmptyVector'.+--+--   @since 0.1+fromVector :: NonEmptyVector a -> CircularVector a+fromVector v = CircularVector v 0+{-# inline fromVector #-}++-- | /O(1)/ Construct a 'CircularVector' from a 'NonEmptyVector'.+--+--   @since 0.1.2+fromVector' :: Vector a -> Maybe (CircularVector a)+fromVector' v = CircularVector <$> NonEmpty.fromVector v <*> pure 0+{-# inline fromVector' #-}++-- | /O(1)/ Construct a 'CircularVector' from a 'Vector'.+--+--   Calls @'error'@ if the input vector is empty.+--+--   @since 0.1+unsafeFromVector :: Vector a -> CircularVector a+unsafeFromVector = fromVector . NonEmpty.unsafeFromVector++-- | /O(n)/ Convert from a circular vector to a list.+--+--+-- >>> let nev = unsafeFromList [1..3] in toList nev+-- [1,2,3]+--+--   @since 0.1.2+toList :: CircularVector a -> [a]+toList = Vector.toList . toVector++-- | /O(n)/ Construct a 'CircularVector' from a list.+--+--   @since 0.1+fromList :: [a] -> Maybe (CircularVector a)+fromList xs = fromListN (Prelude.length xs) xs+{-# inline fromList #-}++-- | Construct a 'CircularVector' from a list with a size hint.+--+--   @since 0.1+fromListN :: Int -> [a] -> Maybe (CircularVector a)+fromListN n xs = fromVector <$> (NonEmpty.fromListN n xs)+{-# inline fromListN #-}++-- | /O(n)/ Construct a 'CircularVector' from a list.+--+--   Calls @'error'@ if the input list is empty.+--+--   @since 0.1+unsafeFromList :: [a] -> CircularVector a+unsafeFromList xs = unsafeFromListN (Prelude.length xs) xs++-- | /O(n)/ Construct a 'CircularVector' from a list with a size hint.+--+--   Calls @'error'@ if the input list is empty, or+--   if the size hint is @'<=' 0@.+--+--    @since 0.1+unsafeFromListN :: Int -> [a] -> CircularVector a+unsafeFromListN n xs+  | n <= 0 = error "Data.Vector.Circular.unsafeFromListN: invalid length!"+  | otherwise = unsafeFromVector (Vector.fromListN n xs)++-- | /O(1)/ Construct a singleton 'CircularVector.+--+--   @since 0.1+singleton :: a -> CircularVector a+singleton = fromVector . NonEmpty.singleton+{-# inline singleton #-}++-- | /O(1)/ Index into a 'CircularVector'. This is always total.+--+--   @since 0.1+index :: CircularVector a -> Int -> a+index (CircularVector v r) = \ !ix ->+  let len = NonEmpty.length v+  in NonEmpty.unsafeIndex v (unsafeMod (ix + r) len)+{-# inline index #-}++-- | /O(1)/ Get the first element of a 'CircularVector'. This is always total.+--+--   @since 0.1+head :: CircularVector a -> a+head v = index v 0+{-# inline head #-}++-- | /O(1)/ Get the last element of a 'CircularVector'. This is always total.+--+--   @since 0.1+last :: CircularVector a -> a+last v = index v (Data.Vector.Circular.length v - 1)+{-# inline last #-}++-- | /O(1)/ Rotate the vector to left by @n@ number of elements.+--+--   /Note/: Right rotations start to break down due to+--   arithmetic overflow when the size of the input vector is+--   @'>' 'maxBound' @'Int'@+--+--   @since 0.1+rotateRight :: Int -> CircularVector a -> CircularVector a+rotateRight r' (CircularVector v r) = CircularVector v h+  where+    len = NonEmpty.length v+    h = unsafeMod (r + unsafeMod r' len) len+{-# inline rotateRight #-}++-- | /O(1)/ Rotate the vector to the left by @n@ number of elements.+--+--   /Note/: Left rotations start to break down due to+--   arithmetic underflow when the size of the input vector is+--   @'>' 'maxBound' @'Int'@+--+--   @since 0.1+rotateLeft :: Int -> CircularVector a -> CircularVector a+rotateLeft r' (CircularVector v r) = CircularVector v h+  where+    len = NonEmpty.length v+    h = unsafeMod (r - unsafeMod r' len) len+{-# inline rotateLeft #-}++-- | Construct a 'CircularVector' at compile-time using+--   typed Template Haskell.+--+--   @since 0.1+vec :: Lift a => [a] -> Q (TExp (CircularVector a))+vec [] = fail "Cannot create an empty CircularVector!"+vec xs =+#if MIN_VERSION_template_haskell(2,16,0)+  liftTyped (unsafeFromList xs)+#else+  unsafeTExpCoerce [|unsafeFromList xs|]+#endif /* MIN_VERSION_template_haskell(2,16,0) */++-- | @since 0.1+equivalent :: Ord a => CircularVector a -> CircularVector a -> Bool+equivalent x y = vector (canonise x) == vector (canonise y)++-- | @since 0.1+canonise :: Ord a => CircularVector a -> CircularVector a+canonise (CircularVector v r) = CircularVector v' (r - lr)+  where+    lr = leastRotation (NonEmpty.toVector v)+    v' = toNonEmptyVector (rotateRight lr (CircularVector v 0))++-- | @since 0.1+leastRotation :: forall a. (Ord a) => Vector a -> Int+leastRotation v = runST go+  where+    go :: forall s. ST s Int+    go = do+      let s = v <> v+      let len = Vector.length s+      f <- MVector.replicate @_ @Int len (-1)+      kVar <- newMutVar @_ @Int 0+      Control.Monad.forM_ [1..len-1] $ \j -> do+        sj <- Vector.indexM s j+        i0 <- readMutVar kVar >>= \k -> MVector.read f (j - k - 1)+        let loop i = do+              a <- readMutVar kVar >>= \k -> Vector.indexM s (k + i + 1)+              if (i /= (-1) && sj /= a)+                then do+                  Control.Monad.when (sj < a) (writeMutVar kVar (j - i - 1))+                  loop =<< MVector.read f i+                else pure i+        i <- loop i0+        a <- readMutVar kVar >>= \k -> Vector.indexM s (k + i + 1)+        if sj /= a+          then do+            readMutVar kVar >>= \k -> Control.Monad.when (sj < (s Vector.! k)) (writeMutVar kVar j)+            readMutVar kVar >>= \k -> MVector.write f (j - k) (-1)+          else do+            readMutVar kVar >>= \k -> MVector.write f (j - k) (i + 1)+      readMutVar kVar++-- only safe if second argument is nonzero.+-- used internally for modulus operations with length.+unsafeMod :: Int -> Int -> Int+unsafeMod = GHC.Base.modInt+{-# inline unsafeMod #-}++-- | /O(min(m,n))/ Zip two circular vectors with the given function.+--+--   @since 0.1.1+zipWith :: (a -> b -> c) -> CircularVector a -> CircularVector b -> CircularVector c+zipWith f a b = fromVector $ NonEmpty.zipWith f (toNonEmptyVector a) (toNonEmptyVector b)++-- | Zip three circular vectors with the given function.+--+--   @since 0.1.1+zipWith3 :: (a -> b -> c -> d) -> CircularVector a -> CircularVector b -> CircularVector c+  -> CircularVector d+zipWith3 f a b c = fromVector $+  NonEmpty.zipWith3 f (toNonEmptyVector a) (toNonEmptyVector b) (toNonEmptyVector c)++-- | /O(min(n,m))/ Elementwise pairing of circular vector elements.+--   This is a special case of 'zipWith' where the function argument is '(,)'+--+--   @since 0.1.1+zip :: CircularVector a -> CircularVector b -> CircularVector (a,b)+zip a b = fromVector $ NonEmpty.zip (toNonEmptyVector a) (toNonEmptyVector b)++-- | Zip together three circular vectors.+--+--   @since 0.1.1+zip3 :: CircularVector a -> CircularVector b -> CircularVector c -> CircularVector (a,b,c)+zip3 a b c = fromVector $ NonEmpty.zip3 (toNonEmptyVector a) (toNonEmptyVector b) (toNonEmptyVector c)++-- | /O(n)/ Reverse a circular vector.+--+--   @since 0.1.1+reverse :: CircularVector a -> CircularVector a+reverse = fromVector . NonEmpty.reverse . toNonEmptyVector++-- | /O(n)/ Rotate to the minimum element of the circular vector according to the+--   given comparison function.+--+--   @since 0.1.1+rotateToMinimumBy :: (a -> a -> Ordering) -> CircularVector a -> CircularVector a+rotateToMinimumBy f (CircularVector v _rot) =+  CircularVector v (NonEmpty.minIndexBy f v)++-- | /O(n)/ Rotate to the maximum element of the circular vector according to the+--   given comparison function.+--+--   @since 0.1.1+rotateToMaximumBy :: (a -> a -> Ordering) -> CircularVector a -> CircularVector a+rotateToMaximumBy f (CircularVector v _rot) =+  CircularVector v (NonEmpty.maxIndexBy f v)++-- | /O(n)/ Check if all elements satisfy the predicate.+--+--   @since 0.1.1+all :: (a -> Bool) -> CircularVector a -> Bool+all f = NonEmpty.all f . vector++-- | /O(n)/ Check if any element satisfies the predicate.+--+--   @since 0.1.1+any :: (a -> Bool) -> CircularVector a -> Bool+any f = NonEmpty.any f . vector++-- | /O(n)/ Check if all elements are True.+--+--   @since 0.1.1+and :: CircularVector Bool -> Bool+and = NonEmpty.and . vector++-- | /O(n)/ Check if any element is True.+--+--   @since 0.1.1+or :: CircularVector Bool -> Bool+or = NonEmpty.or . vector++-- | /O(n)/ Compute the sum of the elements.+--+--   @since 0.1.1+sum :: Num a => CircularVector a -> a+sum = NonEmpty.sum . vector++-- | /O(n)/ Compute the product of the elements.+--+--   @since 0.1.1+product :: Num a => CircularVector a -> a+product = NonEmpty.sum . vector++-- | /O(n)/ Yield the maximum element of the circular vector.+--+--   @since 0.1.1+maximum :: Ord a => CircularVector a -> a+maximum = NonEmpty.maximum . vector++-- | /O(n)/ Yield the maximum element of a circular vector according to the+--   given comparison function.+--+--   @since 0.1.1+maximumBy :: (a -> a -> Ordering) -> CircularVector a -> a+maximumBy f = NonEmpty.maximumBy f . vector++-- | /O(n)/ Yield the minimum element of the circular vector.+--+--   @since 0.1.1+minimum :: Ord a => CircularVector a -> a+minimum = NonEmpty.minimum . vector++-- | /O(n)/ Yield the minimum element of a circular vector according to the+--   given comparison function.+--+--   @since 0.1.1+minimumBy :: (a -> a -> Ordering) -> CircularVector a -> a+minimumBy f = NonEmpty.minimumBy f . vector++-- | /O(n)/ Circular vector of the given length with the same value in+-- each position.+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--   @since 0.1.2+--+-- >>> replicate 3 "a"+-- Just (CircularVector {vector = ["a","a","a"], rotation = 0})+--+-- >>> replicate 0 "a"+-- Nothing+--+replicate :: Int -> a -> Maybe (CircularVector a)+replicate n a = fromVector' (Vector.replicate n a)++-- | /O(n)/ Circular vector of the given length with the same value in+-- each position.+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--   @since 0.1.2+--+-- >>> replicate1 3 "a"+-- CircularVector {vector = ["a","a","a"], rotation = 0}+--+-- >>> replicate1 0 "a"+-- CircularVector {vector = ["a"], rotation = 0}+--+-- >>> replicate1 (-1) "a"+-- CircularVector {vector = ["a"], rotation = 0}+replicate1 :: Int -> a -> CircularVector a+replicate1 n a = unsafeFromVector (Vector.replicate (max n 1) a)++-- | /O(n)/ Construct a circular vector of the given length by applying the function to+-- each index.+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--   @since 0.1.2+--+-- >>> let f 0 = "a"; f _ = "k"; f :: Int -> String+--+-- >>> generate 1 f+-- Just (CircularVector {vector = ["a"], rotation = 0})+--+-- >>> generate 0 f+-- Nothing+--+-- >>> generate 2 f+-- Just (CircularVector {vector = ["a","k"], rotation = 0})+--+generate :: Int -> (Int -> a) -> Maybe (CircularVector a)+generate n f = fromVector' (Vector.generate n f)++-- | /O(n)/ Construct a circular vector of the given length by applying the function to+-- each index.+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--   @since 0.1.2+--+-- >>> let f 0 = "a"; f _ = "k"; f :: Int -> String+--+-- >>> toList $ generate1 2 f+-- ["a","k"]+--+-- >>> toList $ generate1 0 f+-- ["a"]+--+-- >>> toList $ generate1 (-1) f+-- ["a"]+--+generate1 :: Int -> (Int -> a) -> CircularVector a+generate1 n f = unsafeFromVector (Vector.generate (max n 1) f)++-- | /O(n)/ Apply function n times to value. Zeroth element is original value.+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--   @since 0.1.2+--+-- >>> iterateN 3 (+1) 0+-- Just (CircularVector {vector = [0,1,2], rotation = 0})+--+-- >>> iterateN 0 (+1) 0+-- Nothing+--+-- >>> iterateN (-1) (+1) 0+-- Nothing+--+iterateN :: Int -> (a -> a) -> a -> Maybe (CircularVector a)+iterateN n f a = fromVector' (Vector.iterateN n f a)++-- | /O(n)/ Apply function n times to value. Zeroth element is original value.+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--   @since 0.1.2+--+-- >>> iterateN1 3 (+1) 0+-- CircularVector {vector = [0,1,2], rotation = 0}+--+-- >>> iterateN1 0 (+1) 0+-- CircularVector {vector = [0], rotation = 0}+--+-- >>> iterateN1 (-1) (+1) 0+-- CircularVector {vector = [0], rotation = 0}+--+iterateN1 :: Int -> (a -> a) -> a -> CircularVector a+iterateN1 n f a = unsafeFromVector (Vector.iterateN (max n 1) f a)++-- | /O(n)/ Execute the monadic action the given number of times and store+-- the results in a circular vector.+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--   @since 0.1.2+--+-- >>> replicateM @Maybe 3 (Just "a")+-- Just (Just (CircularVector {vector = ["a","a","a"], rotation = 0}))+--+-- >>> replicateM @Maybe 3 Nothing+-- Nothing+--+-- >>> replicateM @Maybe 0 (Just "a")+-- Just Nothing+--+-- >>> replicateM @Maybe (-1) (Just "a")+-- Just Nothing+--+replicateM :: Monad m => Int -> m a -> m (Maybe (CircularVector a))+replicateM n a = fmap fromVector' (Vector.replicateM n a)++-- | /O(n)/ Execute the monadic action the given number of times and store+-- the results in a circular vector.+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--   @since 0.1.2+--+-- >>> replicate1M @Maybe 3 (Just "a")+-- Just (CircularVector {vector = ["a","a","a"], rotation = 0})+--+-- >>> replicate1M @Maybe 3 Nothing+-- Nothing+--+-- >>> replicate1M @Maybe 0 (Just "a")+-- Just (CircularVector {vector = ["a"], rotation = 0})+--+-- >>> replicate1M @Maybe (-1) (Just "a")+-- Just (CircularVector {vector = ["a"], rotation = 0})+--+replicate1M :: Monad m => Int -> m a -> m (CircularVector a)+replicate1M n a = fmap unsafeFromVector (Vector.replicateM (max n 1) a)++-- | /O(n)/ Construct a circular vector of the given length by applying the monadic+-- action to each index+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--   @since 0.1.2+--+-- >>> generateM 3 (\i -> if i < 1 then ["a"] else ["b"])+-- [Just (CircularVector {vector = ["a","b","b"], rotation = 0})]+--+-- >>> generateM @[] @Int 3 (const [])+-- []+--+-- >>> generateM @[] @Int 0 (const [1])+-- [Nothing]+--+-- >>> generateM @Maybe @Int (-1) (const Nothing)+-- Just Nothing+--+generateM :: Monad m => Int -> (Int -> m a) -> m (Maybe (CircularVector a))+generateM n f = fmap fromVector' (Vector.generateM n f)++-- | /O(n)/ Construct a circular vector of the given length by applying the monadic+-- action to each index+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--   @since 0.1.2+--+-- >>> generate1M 3 (\i -> if i < 1 then Just "a" else Just "b")+-- Just (CircularVector {vector = ["a","b","b"], rotation = 0})+--+-- >>> generate1M 3 (const [])+-- []+--+-- >>> generate1M 0 (const $ Just 1)+-- Just (CircularVector {vector = [1], rotation = 0})+--+-- >>> generate1M (-1) (const Nothing)+-- Nothing+--+generate1M :: Monad m => Int -> (Int -> m a) -> m (CircularVector a)+generate1M n f = fmap unsafeFromVector (Vector.generateM (max n 1) f)++-- | /O(n)/ Apply monadic function n times to value. Zeroth element is+-- original value.+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--   @since 0.1.2+--+-- >>> iterateNM @Maybe 3 return "a"+-- Just (Just (CircularVector {vector = ["a","a","a"], rotation = 0}))+--+-- >>> iterateNM @Maybe 3 (const Nothing) "a"+-- Nothing+--+-- >>> iterateNM @Maybe 0 return "a"+-- Just Nothing+--+iterateNM :: Monad m => Int -> (a -> m a) -> a -> m (Maybe (CircularVector a))+iterateNM n f a = fmap fromVector' (Vector.iterateNM n f a)++-- | /O(n)/ Apply monadic function n times to value. Zeroth element is+-- original value.+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--   @since 0.1.2+--+-- >>> iterateN1M @Maybe 3 return "a"+-- Just (CircularVector {vector = ["a","a","a"], rotation = 0})+--+-- >>> iterateN1M @Maybe 3 (const Nothing) "a"+-- Nothing+--+-- >>> iterateN1M @Maybe 0 return "a"+-- Just (CircularVector {vector = ["a"], rotation = 0})+--+-- >>> iterateN1M @Maybe (-1) return "a"+-- Just (CircularVector {vector = ["a"], rotation = 0})+--+iterateN1M :: Monad m => Int -> (a -> m a) -> a -> m (CircularVector a)+iterateN1M n f a = fmap unsafeFromVector (Vector.iterateNM (max n 1) f a)++-- | Execute the monadic action and freeze the resulting circular vector.+--+--   @since 0.1.2+create :: (forall s. ST s (MVector.MVector s a)) -> Maybe (CircularVector a)+create p = fromVector' (Vector.create p)++-- | Execute the monadic action and freeze the resulting circular vector,+-- bypassing emptiness checks.+--+-- The onus is on the caller to guarantee the created vector is non-empty.+--+--   @since 0.1.2+unsafeCreate :: (forall s. ST s (MVector.MVector s a)) -> CircularVector a+unsafeCreate p = unsafeFromVector (Vector.create p)++-- | Execute the monadic action and freeze the resulting circular vector.+--+--   @since 0.1.2+createT+    :: Traversable t+    => (forall s. ST s (t (MVector.MVector s a)))+    -> t (Maybe (CircularVector a))+createT p = fmap fromVector' (Vector.createT p)++-- | Execute the monadic action and freeze the resulting circular vector.+--+-- The onus is on the caller to guarantee the created vector is non-empty.+--+--   @since 0.1.2+unsafeCreateT+    :: Traversable t+    => (forall s. ST s (t (MVector.MVector s a)))+    -> t (CircularVector a)+unsafeCreateT p = fmap unsafeFromVector (Vector.createT p)++-- | /O(n)/ Construct a circular vector by repeatedly applying the+-- generator function to a seed. The generator function yields 'Just' the+-- next element and the new seed or 'Nothing' if there are no more+-- elements.+--+-- If an unfold does not create meaningful values, 'Nothing' is+-- returned. Otherwise, 'Just' containing a circular vector is returned.+--+--   @since 0.1.2+--+-- >>> unfoldr (\b -> case b of "a" -> Just ("a", "b"); _ ->  Nothing) "a"+-- Just (CircularVector {vector = ["a"], rotation = 0})+--+-- >>> unfoldr (const Nothing) "a"+-- Nothing+--+unfoldr :: (b -> Maybe (a, b)) -> b -> Maybe (CircularVector a)+unfoldr f b = fromVector' (Vector.unfoldr f b)++-- | /O(n)/ Construct a circular vector by repeatedly applying the+-- generator function to a seed and a first element.+--+-- This variant of 'unfoldr' guarantees the resulting vector is non-+-- empty by supplying an initial element @a@.+--+--   @since 0.1.2+--+-- >>> unfoldr1 (\b -> case b of "a" -> Just ("a", "b"); _ ->  Nothing) "first" "a"+-- CircularVector {vector = ["first","a"], rotation = 0}+--+-- >>> unfoldr1 (const Nothing) "first" "a"+-- CircularVector {vector = ["first"], rotation = 0}+--+unfoldr1 :: (b -> Maybe (a, b)) -> a -> b -> CircularVector a+unfoldr1 f a b = cons a (unsafeFromVector (Vector.unfoldr f b))++-- | /O(n)/ Construct a circular vector with at most n elements by repeatedly+-- applying the generator function to a seed. The generator function yields+-- 'Just' the next element and the new seed or 'Nothing' if there are no+-- more elements.+--+-- If an unfold does not create meaningful values, 'Nothing' is+-- returned. Otherwise, 'Just' containing a circular vector is returned.+--+--   @since 0.1.2+--+-- >>> unfoldrN 3 (\b -> Just (b+1, b+1)) 0+-- Just (CircularVector {vector = [1,2,3], rotation = 0})+--+-- >>> unfoldrN 3 (const Nothing) 0+-- Nothing+--+-- >>> unfoldrN 0 (\b -> Just (b+1, b+1)) 0+-- Nothing+--+unfoldrN :: Int -> (b -> Maybe (a, b)) -> b -> Maybe (CircularVector a)+unfoldrN n f b = fromVector' (Vector.unfoldrN n f b)++-- | /O(n)/ Construct a circular vector with at most n elements by repeatedly+-- applying the generator function to a seed. The generator function yields+-- 'Just' the next element and the new seed or 'Nothing' if there are no+-- more elements.+--+-- This variant of 'unfoldrN' guarantees the resulting vector is non-+-- empty by supplying an initial element @a@.+--+--   @since 0.1.2+--+-- >>> unfoldr1N 3 (\b -> Just (b+1, b+1)) 0 0+-- CircularVector {vector = [0,1,2,3], rotation = 0}+--+-- >>> unfoldr1N 3 (const Nothing) 0 0+-- CircularVector {vector = [0], rotation = 0}+--+-- >>> unfoldr1N 0 (\b -> Just (b+1, b+1)) 0 0+-- CircularVector {vector = [0], rotation = 0}+--+unfoldr1N+    :: Int+    -> (b -> Maybe (a, b))+    -> a+    -> b+    -> CircularVector a+unfoldr1N n f a b = cons a (unsafeFromVector (Vector.unfoldrN n f b))++-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator+-- function to a seed. The generator function yields Just the next element+-- and the new seed or Nothing if there are no more elements.+--+-- If an unfold does not create meaningful values, 'Nothing' is+-- returned. Otherwise, 'Just' containing a circular vector is returned.+--+--   @since 0.1.2+unfoldrM+    :: Monad m+    => (b -> m (Maybe (a, b)))+    -> b+    -> m (Maybe (CircularVector a))+unfoldrM f b = fmap fromVector' (Vector.unfoldrM f b)++-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator+-- function to a seed. The generator function yields Just the next element+-- and the new seed or Nothing if there are no more elements.+--+-- This variant of 'unfoldrM' guarantees the resulting vector is non-+-- empty by supplying an initial element @a@.+--+--   @since 0.1.2+unfoldr1M+    :: Monad m+    => (b -> m (Maybe (a, b)))+    -> a+    -> b+    -> m (CircularVector a)+unfoldr1M f a b = fmap (cons a . unsafeFromVector) (Vector.unfoldrM f b)++-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator+-- function to a seed. The generator function yields Just the next element and+-- the new seed or Nothing if there are no more elements.+--+-- If an unfold does not create meaningful values, 'Nothing' is+-- returned. Otherwise, 'Just' containing a circular vector is returned.+--+--   @since 0.1.2+unfoldrNM+    :: Monad m+    => Int+    -> (b -> m (Maybe (a, b)))+    -> b+    -> m (Maybe (CircularVector a))+unfoldrNM n f b = fmap fromVector' (Vector.unfoldrNM n f b)++-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator+-- function to a seed. The generator function yields Just the next element and+-- the new seed or Nothing if there are no more elements.+--+-- This variant of 'unfoldrNM' guarantees the resulting vector is non-+-- empty by supplying an initial element @a@.+--+--   @since 0.1.2+unfoldr1NM+    :: Monad m+    => Int+    -> (b -> m (Maybe (a, b)))+    -> a+    -> b+    -> m (CircularVector a)+unfoldr1NM n f a b = fmap (cons a . unsafeFromVector) (Vector.unfoldrNM n f b)++-- | /O(n)/ Construct a circular vector with n elements by repeatedly applying the+-- generator function to the already constructed part of the vector.+--+-- If 'constructN' does not create meaningful values, 'Nothing' is+-- returned. Otherwise, 'Just' containing a circular vector is returned.+--+--   @since 0.1.2+constructN :: Int -> (Vector a -> a) -> Maybe (CircularVector a)+constructN n f = fromVector' (Vector.constructN n f)++-- | /O(n)/ Construct a circular vector with n elements from right to left by repeatedly+-- applying the generator function to the already constructed part of the vector.+--+-- If 'constructrN' does not create meaningful values, 'Nothing' is+-- returned. Otherwise, 'Just' containing a circular vector is returned.+--+--   @since 0.1.2+constructrN :: Int -> (Vector a -> a) -> Maybe (CircularVector a)+constructrN n f = fromVector' (Vector.constructrN n f)++-- | /O(n)/ Yield a circular vector of the given length containing the+-- values x, x+1 etc. This operation is usually more efficient than+-- 'enumFromTo'.+--+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,+-- otherwise, 'Just' containing a circular vector.+--+--   @since 0.1.2+enumFromN :: Num a => a -> Int -> Maybe (CircularVector a)+enumFromN a n = fromVector' (Vector.enumFromN a n)++-- | /O(n)/ Yield a circular vector of length @max n 1@ containing the+-- values x, x+1 etc. This operation is usually more efficient than+-- 'enumFromTo'.+--+--   @since 0.1.2+enumFromN1 :: Num a => a -> Int -> CircularVector a+enumFromN1 a n = unsafeFromVector (Vector.enumFromN a (max n 1))++-- | /O(n)/ Yield a circular vector of the given length containing the+-- values x, x+y, x+y+y etc. This operations is usually more efficient than+-- 'enumFromThenTo'.+--+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,+-- otherwise, 'Just' containing a circular vector.+--+--   @since 0.1.2+enumFromStepN :: Num a => a -> a -> Int -> Maybe (CircularVector a)+enumFromStepN a0 a1 n = fromVector' (Vector.enumFromStepN a0 a1 n)++-- | /O(n)/ Yield a circular vector of length @max n 1@ containing the+-- values x, x+y, x+y+y etc. This operations is usually more efficient than+-- 'enumFromThenTo'.+--+--   @since 0.1.2+enumFromStepN1 :: Num a => a -> a -> Int -> CircularVector a+enumFromStepN1 a0 a1 n = unsafeFromVector (Vector.enumFromStepN a0 a1 (max n 1))++-- | /O(n)/ Enumerate values from x to y.+--+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,+-- otherwise, 'Just' containing a circular vector.+--+-- /WARNING/: This operation can be very inefficient. If at all possible,+-- use 'enumFromN' instead.+--+--+--   @since 0.1.2+enumFromTo :: Enum a => a -> a -> Maybe (CircularVector a)+enumFromTo a0 a1 = fromVector' (Vector.enumFromTo a0 a1)++-- | /O(n)/ Enumerate values from x to y with a specific step z.+--+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,+-- otherwise, 'Just' containing a circular vector.+--+-- /WARNING/: This operation can be very inefficient. If at all possible,+-- use 'enumFromStepN' instead.+--+--   @since 0.1.2+enumFromThenTo :: Enum a => a -> a -> a -> Maybe (CircularVector a)+enumFromThenTo a0 a1 a2 = fromVector' (Vector.enumFromThenTo a0 a1 a2)++-- | /O(n)/ Prepend an element+--+--   @since 0.1.2+--+-- >>> cons 1 (unsafeFromList [2,3])+-- CircularVector {vector = [1,2,3], rotation = 0}+--+cons :: a -> CircularVector a -> CircularVector a+cons a cv = consV a (toVector cv)+{-# INLINE cons #-}++-- | /O(n)/ Prepend an element to a Vector+--+--   @since 0.1.2+--+-- >>> consV 1 (Vector.fromList [2,3])+-- CircularVector {vector = [1,2,3], rotation = 0}+--+consV :: a -> Vector a -> CircularVector a+consV a = fromVector . NonEmpty.consV a+{-# INLINE consV #-}++-- | /O(n)/ Append an element+--+--   @since 0.1.2+--+-- >>> snoc (unsafeFromList [1,2]) 3+-- CircularVector {vector = [1,2,3], rotation = 0}+--+snoc :: CircularVector a -> a -> CircularVector a+snoc = snocV . toVector++-- | /O(n)/ Append an element to a Vector+--+--   @since 0.1.2+--+-- >>> snocV (Vector.fromList [1,2]) 3+-- CircularVector {vector = [1,2,3], rotation = 0}+--+snocV :: Vector a -> a -> CircularVector a+snocV as = fromVector . NonEmpty.snocV as++-- | /O(m+n)/ Concatenate two circular vectors+--+--   @since 0.1.2+--+-- >>> (unsafeFromList [1..3]) ++ (unsafeFromList [4..6])+-- CircularVector {vector = [1,2,3,4,5,6], rotation = 0}+--+(++) :: CircularVector a -> CircularVector a -> CircularVector a+v ++ v' = fromVector (toNonEmptyVector v NonEmpty.++ toNonEmptyVector v')++-- | /O(n)/ Concatenate all circular vectors in the list+--+-- If list is empty, 'Nothing' is returned, otherwise 'Just'+-- containing the concatenated circular vectors+--+--   @since 0.1.2+--+-- >>> concat [(unsafeFromList [1..3]), (unsafeFromList [4..6])]+-- Just (CircularVector {vector = [1,2,3,4,5,6], rotation = 0})+--+concat :: [CircularVector a] -> Maybe (CircularVector a)+concat [] = Nothing+concat (a:as) = Just (concat1 (a :| as))+{-# INLINE concat #-}++-- | O(n) Concatenate all circular vectors in a non-empty list.+--+--   @since 0.1.2+--+-- >>> concat1 ((unsafeFromList [1..3]) :| [(unsafeFromList [4..6])])+-- CircularVector {vector = [1,2,3,4,5,6], rotation = 0}+--+concat1 :: NonEmpty (CircularVector a) -> CircularVector a+concat1 = fromVector . NonEmpty.concat1 . fmap toNonEmptyVector++-- | /O(n)/ Map a function over a circular vector.+--+--   @since 0.1.2+--+-- >>> map (+1) $ unsafeFromList [1..3]+-- CircularVector {vector = [2,3,4], rotation = 0}+--+map :: (a -> b) -> CircularVector a -> CircularVector b+map f (CircularVector v rot) = CircularVector (NonEmpty.map f v) rot++-- | /O(n)/ Apply a function to every element of a circular vector and+-- its index.+--+--   @since 0.1.2+--+-- >>> imap (\i a -> if i == 2 then a+1 else a+0) $ unsafeFromList [1..3]+-- CircularVector {vector = [1,2,4], rotation = 0}+--+imap :: (Int -> a -> b) -> CircularVector a -> CircularVector b+imap f = fromVector . NonEmpty.imap f . toNonEmptyVector++-- | Map a function over a circular vector and concatenate the results.+--+--   @since 0.1.2+--+-- >>> concatMap (\a -> unsafeFromList [a,a]) (unsafeFromList [1,2,3])+-- CircularVector {vector = [1,1,2,2,3,3], rotation = 0}+--+concatMap+    :: (a -> CircularVector b)+    -> CircularVector a+    -> CircularVector b+concatMap f = fromVector . NonEmpty.concatMap (toNonEmptyVector . f) . toNonEmptyVector++-- | /O(n)/ Apply the monadic action to all elements of the circular+-- vector, yielding circular vector of results.+--+--   @since 0.1.2+--+-- >>> mapM Just (unsafeFromList [1..3])+-- Just (CircularVector {vector = [1,2,3], rotation = 0})+--+-- >>> mapM (const Nothing) (unsafeFromList [1..3])+-- Nothing+--+mapM :: Monad m => (a -> m b) -> CircularVector a -> m (CircularVector b)+mapM f = fmap fromVector . NonEmpty.mapM f . toNonEmptyVector++-- | /O(n)/ Apply the monadic action to every element of a circular+-- vector and its index, yielding a circular vector of results.+--+--   @since 0.1.2+--+-- >>> imapM (\i a -> if i == 1 then Just a else Just 0) (unsafeFromList [1..3])+-- Just (CircularVector {vector = [0,2,0], rotation = 0})+--+-- >>> imapM (\_ _ -> Nothing) (unsafeFromList [1..3])+-- Nothing+--+imapM+    :: Monad m+    => (Int -> a -> m b)+    -> CircularVector a+    -> m (CircularVector b)+imapM f = fmap fromVector . NonEmpty.imapM f . toNonEmptyVector++-- | /O(n)/ Apply the monadic action to all elements of a circular vector+-- and ignore the results.+--+--   @since 0.1.2+--+-- >>> mapM_ (const $ Just ()) (unsafeFromList [1..3])+-- Just ()+--+-- >>> mapM_ (const Nothing) (unsafeFromList [1..3])+-- Nothing+--+mapM_ :: Monad m => (a -> m b) -> CircularVector a -> m ()+mapM_ f = NonEmpty.mapM_ f . toNonEmptyVector++-- | /O(n)/ Apply the monadic action to every element of a circular+-- vector and its index, ignoring the results+--+--   @since 0.1.2+--+-- >>> imapM_ (\i a -> if i == 1 then print a else putStrLn "0") (unsafeFromList [1..3])+-- 0+-- 2+-- 0+--+-- >>> imapM_ (\_ _ -> Nothing) (unsafeFromList [1..3])+-- Nothing+--+imapM_ :: Monad m => (Int -> a -> m b) -> CircularVector a -> m ()+imapM_ f = NonEmpty.imapM_ f . toNonEmptyVector++-- | /O(n)/ Apply the monadic action to all elements of the circular+-- vector, yielding a circular vector of results.+--+-- Equivalent to @flip 'mapM'@.+--+--   @since 0.1.2+forM :: Monad m => CircularVector a -> (a -> m b) -> m (CircularVector b)+forM cv f = fromVector <$> NonEmpty.forM (toNonEmptyVector cv) f++-- | /O(n)/ Apply the monadic action to all elements of a circular+-- vector and ignore the results.+--+-- Equivalent to @flip 'mapM_'@.+--+--   @since 0.1.2+forM_ :: Monad m => CircularVector a -> (a -> m b) -> m ()+forM_ cv f = NonEmpty.forM_ (toNonEmptyVector cv) f++-- | /O(n)/ Drop repeated adjacent elements.+--+-- >>> toList $ uniq $ unsafeFromList [1,1,2,2,3,3,1]+-- [1,2,3]+--+-- >>> toList $ uniq $ unsafeFromList [1,2,3,1]+-- [1,2,3]+--+-- >>> toList $ uniq $ unsafeFromList [1]+-- [1]+uniq :: Eq a => CircularVector a -> CircularVector a+uniq = fromVector . trim . NonEmpty.uniq . toNonEmptyVector+  where+    trim v+      | Foldable.length v == 1 || NonEmpty.head v /= NonEmpty.last v+        = v+      | otherwise+        = trim (NonEmpty.unsafeFromVector $ NonEmpty.init v)++-- | /O(n)/ Drop elements when predicate returns Nothing+--+-- If no elements satisfy the predicate, the resulting vector may be empty.+--+--   @since 0.1.2+--+-- >>> mapMaybe (\a -> if a == 2 then Nothing else Just a) (unsafeFromList [1..3])+-- [1,3]+mapMaybe+    :: (a -> Maybe b)+    -> CircularVector a+    -> Vector b+mapMaybe f = NonEmpty.mapMaybe f . toNonEmptyVector++-- | /O(n)/ Drop elements when predicate, applied to index and value, returns Nothing+--+-- If no elements satisfy the predicate, the resulting vector may be empty.+--+--   @since 0.1.2+--+-- >>> imapMaybe (\i a -> if a == 2 || i == 2 then Nothing else Just a) (unsafeFromList [1..3])+-- [1]+--+imapMaybe+    :: (Int -> a -> Maybe b)+    -> CircularVector a+    -> Vector b+imapMaybe f = NonEmpty.imapMaybe f . toNonEmptyVector++-- | /O(n)/ Yield the longest prefix of elements satisfying the predicate+-- without copying.+--+-- If no elements satisfy the predicate, the resulting vector may be empty.+--+--   @since 0.1.2+--+-- >>> takeWhile (/= 3) (unsafeFromList [1..3])+-- [1,2]+--+takeWhile :: (a -> Bool) -> CircularVector a -> Vector a+takeWhile f = NonEmpty.takeWhile f . toNonEmptyVector++-- | /O(n)/ Drop the longest prefix of elements that satisfy the predicate+-- without copying.+--+-- If all elements satisfy the predicate, the resulting vector may be empty.+--+--   @since 0.1.2+--+-- >>> dropWhile (/= 3) (unsafeFromList [1..3])+-- [3]+--+dropWhile :: (a -> Bool) -> CircularVector a -> Vector a+dropWhile f = NonEmpty.dropWhile f . toNonEmptyVector++-- | /O(n)/ Split the circular vector in two parts, the first one+-- containing those elements that satisfy the predicate and the second+-- one those that don't. The relative order of the elements is preserved+-- at the cost of a sometimes reduced performance compared to+-- 'unstablePartition'.+--+-- If all or no elements satisfy the predicate, one of the resulting vectors+-- may be empty.+--+--   @since 0.1.2+--+-- >>> partition (< 3) (unsafeFromList [1..5])+-- ([1,2],[3,4,5])+--+partition :: (a -> Bool) -> CircularVector a -> (Vector a, Vector a)+partition f = NonEmpty.partition f . toNonEmptyVector++-- | /O(n)/ Split the circular vector in two parts, the first one+-- containing those elements that satisfy the predicate and the second+-- one those that don't. The order of the elements is not preserved but+-- the operation is often faster than 'partition'.+--+-- If all or no elements satisfy the predicate, one of the resulting vectors+-- may be empty.+--+--   @since 0.1.2+unstablePartition+    :: (a -> Bool)+    -> CircularVector a+    -> (Vector a, Vector a)+unstablePartition f = NonEmpty.unstablePartition f . toNonEmptyVector++-- | /O(n)/ Split the circular vector into the longest prefix of elements+-- that satisfy the predicate and the rest without copying.+--+-- If all or no elements satisfy the predicate, one of the resulting vectors+-- may be empty.+--+--   @since 0.1.2+--+-- >>> span (== 1) (unsafeFromList [1,1,2,3,1])+-- ([1,1],[2,3,1])+--+span :: (a -> Bool) -> CircularVector a -> (Vector a, Vector a)+span f = NonEmpty.span f . toNonEmptyVector++-- | /O(n)/ Split the circular vector into the longest prefix of elements that do not+-- satisfy the predicate and the rest without copying.+--+-- If all or no elements satisfy the predicate, one of the resulting vectors+-- may be empty.+--+--   @since 0.1.2+--+-- >>> break (== 2) (unsafeFromList [1,1,2,3,1])+-- ([1,1],[2,3,1])+--+break :: (a -> Bool) -> CircularVector a -> (Vector a, Vector a)+break f = NonEmpty.break f . toNonEmptyVector++-- | /O(n)/ Check if the circular vector contains an element+--+--   @since 0.1.2+--+-- >>> elem 1 $ unsafeFromList [1..3]+-- True+-- >>> elem 4 $ unsafeFromList [1..3]+-- False+--+elem :: Eq a => a -> CircularVector a -> Bool+elem a = NonEmpty.elem a . toNonEmptyVector++-- | /O(n)/ Check if the circular vector does not contain an element+-- (inverse of 'elem')+--+--   @since 0.1.2+--+-- >>> notElem 1 $ unsafeFromList [1..3]+-- False+--+-- >>> notElem 4 $ unsafeFromList [1..3]+-- True+--+notElem :: Eq a => a -> CircularVector a -> Bool+notElem a = NonEmpty.notElem a . toNonEmptyVector++-- | /O(n)/ Yield 'Just' the first element matching the predicate or+-- 'Nothing' if no such element exists.+--+--   @since 0.1.2+--+-- >>> find (< 2) $ unsafeFromList [1..3]+-- Just 1+--+-- >>> find (< 0) $ unsafeFromList [1..3]+-- Nothing+--+find :: (a -> Bool) -> CircularVector a -> Maybe a+find f = NonEmpty.find f . toNonEmptyVector++-- | /O(n)/ Yield 'Just' the index of the first element matching the+-- predicate or 'Nothing' if no such element exists.+--+--   @since 0.1.2+--+-- >>> findIndex (< 2) $ unsafeFromList [1..3]+-- Just 0+--+-- >>> findIndex (< 0) $ unsafeFromList [1..3]+-- Nothing+--+-- >>> findIndex (==1) $ rotateRight 1 (unsafeFromList [1..3])+-- Just 2+findIndex :: (a -> Bool) -> CircularVector a -> Maybe Int+findIndex f = NonEmpty.findIndex f . toNonEmptyVector++-- | /O(n)/ Yield the indices of elements satisfying the predicate in+-- ascending order.+--+--   @since 0.1.2+--+-- >>> findIndices (< 3) $ unsafeFromList [1..3]+-- [0,1]+--+-- >>> findIndices (< 0) $ unsafeFromList [1..3]+-- []+--+findIndices :: (a -> Bool) -> CircularVector a -> Vector Int+findIndices f = NonEmpty.findIndices f . toNonEmptyVector++-- | /O(n)/ Yield 'Just' the index of the first occurence of the given+-- element or 'Nothing' if the circular vector does not contain the+-- element. This is a specialised version of 'findIndex'.+--+--   @since 0.1.2+--+-- >>> elemIndex 1 $ unsafeFromList [1..3]+-- Just 0+--+-- >>> elemIndex 0 $ unsafeFromList [1..3]+-- Nothing+--+elemIndex :: Eq a => a -> CircularVector a -> Maybe Int+elemIndex a = NonEmpty.elemIndex a . toNonEmptyVector++-- | /O(n)/ Yield the indices of all occurences of the given element in+-- ascending order. This is a specialised version of 'findIndices'.+--+--   @since 0.1.2+--+-- >>> elemIndices 1 $ unsafeFromList [1,2,3,1]+-- [0,3]+--+-- >>> elemIndices 0 $ unsafeFromList [1..3]+-- []+--+elemIndices :: Eq a => a -> CircularVector a -> Vector Int+elemIndices a = NonEmpty.elemIndices a . toNonEmptyVector++-- | /O(n)/ Drop elements that do not satisfy the predicate which is+-- applied to values and their indices.+--+-- If no elements satisfy the predicate, the resulting vector may be empty.+--+--   @since 0.1.2+--+-- >>> ifilter (\i a -> if a == 2 || i == 0 then False else True) (unsafeFromList [1..3])+-- [3]+--+-- >>> ifilter (\_ _ -> False) (unsafeFromList [1..3])+-- []+--+ifilter+    :: (Int -> a -> Bool)+    -> CircularVector a+    -> Vector a+ifilter f = NonEmpty.ifilter f . toNonEmptyVector++-- | /O(n)/ Drop elements that do not satisfy the monadic predicate.+--+-- If no elements satisfy the predicate, the resulting vector may be empty.+--+--   @since 0.1.2+--+-- >>> filterM (\a -> if a == 2 then Just False else Just True) (unsafeFromList [1..3])+-- Just [1,3]+--+-- >>> filterM (\a -> if a == 2 then Nothing else Just True) (unsafeFromList [1..3])+-- Nothing+--+-- >>> filterM (const $ Just False) (unsafeFromList [1..3])+-- Just []+--+filterM+    :: Monad m+    => (a -> m Bool)+    -> CircularVector a+    -> m (Vector a)+filterM f = NonEmpty.filterM f . toNonEmptyVector++-- | /O(n)/ Drop elements that do not satisfy the monadic predicate that is+-- a function of index and value.+--+-- If no elements satisfy the predicate, the resulting vector may be empty.+--+--   @since 0.1.2+--+-- >>> ifilterM (\i a -> if a == 2 || i == 0 then Just False else Just True) (unsafeFromList [1..3])+-- Just [3]+--+-- >>> ifilterM (\i a -> if a == 2 || i == 0 then Nothing else Just True) (unsafeFromList [1..3])+-- Nothing+--+-- >>> ifilterM (\_ _ -> Just False) (unsafeFromList [1..3])+-- Just []+--+ifilterM+    :: Monad m+    => (Int -> a -> m Bool)+    -> CircularVector a+    -> m (Vector a)+ifilterM f = NonEmpty.ifilterM f . toNonEmptyVector++-- | /O(n)/ Yield the circular vector obtained by replacing each element+-- @i@ of the circular index vector by @xs'!'i@. This is equivalent to+-- @'map' (xs'!') is@ but is often much more efficient.+--+--   @since 0.1.2+--+-- >>> toList $ backpermute (unsafeFromList [1..3]) (unsafeFromList [2,0])+-- [3,1]+--+backpermute :: CircularVector a -> CircularVector Int -> CircularVector a+backpermute v i = fromVector $ NonEmpty.backpermute (toNonEmptyVector v) (toNonEmptyVector i)++-- | Same as 'backpermute' but without bounds checking.+--+--   @since 0.1.2+unsafeBackpermute+    :: CircularVector a+    -> CircularVector Int+    -> CircularVector a+unsafeBackpermute v i = fromVector (NonEmpty.unsafeBackpermute (toNonEmptyVector v) (toNonEmptyVector i))++-- | Apply a destructive operation to a circular vector. The operation+-- will be performed in place if it is safe to do so and will modify a+-- copy of the circular vector otherwise.+--+--   @since 0.1.2+modify+    :: (forall s. MVector.MVector s a -> ST s ())+    -> CircularVector a+    -> CircularVector a+modify p = fromVector . NonEmpty.modify p . toNonEmptyVector
+ src/Data/Vector/Circular/Generic.hs view
@@ -0,0 +1,1769 @@+{-# language+    BangPatterns+  , CPP+  , DeriveAnyClass+  , DeriveFunctor+  , DeriveGeneric+  , DerivingStrategies+  , InstanceSigs+  , ScopedTypeVariables+  , TemplateHaskell+  , TypeApplications+  , RankNTypes+  , FlexibleContexts+#-}++module Data.Vector.Circular.Generic+  ( -- * Types+    CircularVector(..)++    -- * Construction+    -- ** Initialization+  , singleton+  , replicate+  , replicate1+  , generate+  , generate1+  , iterateN+  , iterateN1+    -- ** Monad Initialization+  , replicateM+  , replicate1M+  , generateM+  , generate1M+  , iterateNM+  , iterateN1M+  , create+  , unsafeCreate+  , createT+  , unsafeCreateT+    -- ** Unfolding+  , unfoldr+  , unfoldr1+  , unfoldrN+  , unfoldr1N+  , unfoldrM+  , unfoldr1M+  , unfoldrNM+  , unfoldr1NM+  , constructN+  , constructrN+    -- ** Enumeration+  , enumFromN+  , enumFromN1+  , enumFromStepN+  , enumFromStepN1+  , enumFromTo+  , enumFromThenTo+    -- ** Concatenation+  , cons+  , consV+  , snoc+  , snocV+  , (Data.Vector.Circular.Generic.++)+  , concat+  , concat1+    -- ** Restricting memory usage+  , force++    -- ** Template Haskell+  -- , vec++    -- * Conversion+  , toVector+  , fromVector+  , unsafeFromVector+  , toNonEmptyVector+  , toList+  , fromList+  , fromListN+  , unsafeFromList+  , unsafeFromListN++    -- * Rotation+  , rotateLeft+  , rotateRight++    -- * Comparisons+  , equivalent+  , canonise+  , leastRotation++    -- * Folds+  , foldMap+  , foldMap'+  , foldr+  , foldl+  , foldr'+  , foldl'+  , foldr1+  , foldl1+  , foldMap1+  , foldMap1'+  , toNonEmpty++    -- * Specialized folds+  , all+  , any+  , and+  , or+  , sum+  , product+  , maximum+  , maximumBy+  , minimum+  , minimumBy+  , rotateToMinimumBy+  , rotateToMaximumBy++    -- * Elementwise operations+    -- ** Indexing+  , index+  , head+  , last++    -- ** Mapping+  , map+  , imap+  , concatMap++    -- ** Monadic mapping+  , mapM+  , imapM+  , mapM_+  , imapM_+  , forM+  , forM_++    -- ** Zipping+  , zipWith+  , zipWith3+  , zip+  , zip3++    -- ** Unzipping+  , unzip+  , unzip3++    -- ** Filtering+  , uniq+  , mapMaybe+  , imapMaybe+  , filter+  , ifilter+  , filterM+  -- , ifilterM -- Not in Data.Vector.Generic+  , takeWhile+  , dropWhile++    -- * Partitioning+  , partition+  , unstablePartition+  , span+  , break++    -- * Searching+  , elem+  , notElem+  , find+  , findIndex+  , findIndices+  , elemIndex+  , elemIndices++    -- * Permutations+  , reverse+  , backpermute+  , unsafeBackpermute++    -- * Safe destructive updates+  , modify++    -- * Monadic Sequencing+  , sequence+  , sequence_+  ) where++import qualified Control.Monad (when, forM_)+import Control.Monad.ST (ST, runST)+import Control.DeepSeq+#if MIN_VERSION_base(4,13,0)+-- import Data.Foldable (foldMap')+#endif /* MIN_VERSION_base(4,13,0) */+import Data.List.NonEmpty (NonEmpty((:|)))+import qualified Data.List.NonEmpty as NonEmptyList+import Data.Primitive.MutVar ( newMutVar, readMutVar, writeMutVar )+import Data.Vector.NonEmpty (NonEmptyVector)+import GHC.Base (modInt)+import GHC.Generics (Generic)+import Prelude hiding (head, length, last, map, concat, takeWhile+                      ,dropWhile, span, break, elem, notElem, reverse+                      ,mapM, mapM_, foldMap, foldr+                      ,foldl, foldr1, foldl1, all, any, and, or, sum+                      ,product, maximum, minimum, concatMap+                      ,zipWith, zipWith3, zip, zip3, replicate, enumFromTo+                      ,enumFromThenTo, (++))+import Language.Haskell.TH.Syntax+import qualified Data.Vector.Mutable as MVector+import qualified Data.Vector.NonEmpty as NonEmpty+import qualified Data.Vector.Generic as G+import qualified Prelude+import Data.Monoid+import Data.Coerce+import Data.Maybe ( fromMaybe )++-- $setup+-- >>> import Data.Vector (Vector)+-- >>> import qualified Data.Vector+++-- | A circular, immutable vector. This type is equivalent to+--   @'Data.List.cycle' xs@ for some finite, nonempty @xs@, but+--   with /O(1)/ access and /O(1)/ rotations. Indexing+--   into this type is always total.+data CircularVector v a = CircularVector+  { vector :: !(v a)+  , rotation :: {-# UNPACK #-} !Int+  }+  deriving stock+    ( Functor -- ^ since 0.1.2+    , Generic -- ^ @since 0.1.2+    , Ord     -- ^ since 0.1.2+    , Read    -- ^ since 0.1.2+    , Show    -- ^ since 0.1.2+    )+  deriving anyclass+    ( NFData -- ^ @since 0.1.2+    )++-- | @since 0.1.2+-- instance Traversable (CircularVector v) where+--   traverse :: (Applicative f) => (a -> f b) -> CircularVector a -> f (CircularVector b)+--   traverse f (CircularVector v rot) =+--     CircularVector <$> traverse f v <*> pure rot++-- | since 0.1.2+instance (G.Vector v a, Eq a) => Eq (CircularVector v a) where+  (==) :: CircularVector v a -> CircularVector v a -> Bool+  a == b = toVector a `G.eq` toVector b++-- | @since 0.1.2+-- instance Eq2 CircularVector where+--   liftEq2 :: (a -> b -> Bool) -> CircularVector v a -> CircularVector v b -> Bool+--   liftEq2 eq c0@(CircularVector x rx) c1@(CircularVector y ry)+--     | G.length x /= G.length y = False+--     | rx == ry = liftEq eq x y+--     | otherwise = getAll $ flip Prelude.foldMap [0..NonEmpty.length x-1] $ \i ->+--         All (index c0 i `eq` index c1 i)++-- | @since 0.1.2+-- instance Ord1 CircularVector where+--   liftCompare :: (a -> b -> Ordering) -> CircularVector a -> CircularVector b -> Ordering+--   liftCompare cmp (CircularVector x rx) (CircularVector y ry)+--     = liftCompare cmp x y <> compare rx ry++-- | @since 0.1.2+-- instance Show1 CircularVector where+--   liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> CircularVector a -> ShowS+--   liftShowsPrec sp sl d (CircularVector x rx) =+--     showsBinaryWith (liftShowsPrec sp sl) showsPrec "CircularVector" d x rx++-- | @since 0.1.2+-- instance Read1 CircularVector where+--   liftReadPrec rp rl = readData $+--     readBinaryWith (liftReadPrec rp rl) readPrec "CircularVector" CircularVector+--   liftReadListPrec = liftReadListPrecDefault++-- | The 'Semigroup' @('<>')@ operation behaves by un-rolling+--   the two vectors so that their rotation is 0, concatenating+--   them, returning a new vector with a 0-rotation.+--+--   since 0.1.2+instance (G.Vector v a) => Semigroup (CircularVector v a) where+  (<>) :: CircularVector v a -> CircularVector v a -> CircularVector v a+  lhs <> rhs = CircularVector v 0+    where+      szLhs = length lhs+      szRhs = length rhs+      sz = szLhs + szRhs+      v = G.generate sz+            $ \ix -> if ix < szLhs+                then index lhs ix+                else index rhs (ix - szLhs)+  {-# inline (<>) #-}++-- | since 0.1.2+-- instance Foldable (CircularVector v) where+--   foldMap :: Monoid m => (a -> m) -> CircularVector v a -> m+--   foldMap = Data.Vector.Circular.Generic.foldMap+--   {-# inline foldMap #-}++-- #if MIN_VERSION_base(4,13,0)+--   foldMap' :: Monoid m => (a -> m) -> CircularVector a -> m+--   foldMap' = Data.Vector.Circular.Generic.foldMap'+--   {-# inline foldMap' #-}+-- #endif /* MIN_VERSION_base(4,13,0) */++--   null :: CircularVector a -> Bool+--   null _ = False -- nonempty structure is always not null+--   {-# inline null #-}++--   length :: CircularVector a -> Int+--   length = Data.Vector.Circular.Generic.length+--   {-# inline length #-}++-- | since 0.1.2+-- instance Foldable1 CircularVector where+--   foldMap1 :: Semigroup m => (a -> m) -> CircularVector a -> m+--   foldMap1 = Data.Vector.Circular.Generic.foldMap1+--   {-# inline foldMap1 #-}++-- FIXME: This instance is probably broken.+-- | since 0.1.2+instance Lift a => Lift (CircularVector v a) where+  lift c = do+    v <- [|vector c|]+    r <- [|rotation c|]+    pure $ ConE ''CircularVector+      `AppE` v+      `AppE` r+#if MIN_VERSION_template_haskell(2,16,0)+  liftTyped = unsafeTExpCoerce . lift+#endif /* MIN_VERSION_template_haskell(2,16,0) */++-- | Get the length of a 'CircularVector'.+--+--   since 0.1.2+length :: G.Vector v a => CircularVector v a -> Int+length (CircularVector v _) = G.length v+{-# inline length #-}++-- | Lazily-accumulating monoidal fold over a 'CircularVector'.+--   since 0.1.2+foldMap :: (Monoid m, G.Vector v a) => (a -> m) -> CircularVector v a -> m+foldMap f = \v ->+  let len = Data.Vector.Circular.Generic.length v+      go !ix+        | ix < len = f (index v ix) <> go (ix + 1)+        | otherwise = mempty+  in go 0+{-# inline foldMap #-}++++-- | Strictly-accumulating monoidal fold over a 'CircularVector'.+--+--   since 0.1.2+foldMap' :: (Monoid m, G.Vector v a) => (a -> m) -> CircularVector v a -> m+foldMap' f = \v ->+  let len = Data.Vector.Circular.Generic.length v+      go !ix !acc+        | ix < len = go (ix + 1) (acc <> f (index v ix))+        | otherwise = acc+  in go 0 mempty+{-# inline foldMap' #-}++(#.) :: Coercible b c => (b -> c) -> (a -> b) -> (a -> c)+(#.) _f = coerce+{-# INLINE (#.) #-}++-- | since 0.1.2+foldr :: G.Vector v a => (a -> b -> b) -> b -> CircularVector v a -> b+foldr f z t = appEndo (foldMap (Endo #. f) t) z++-- -- | since 0.1.2+foldl :: G.Vector v a => (b -> a -> b) -> b -> CircularVector v a -> b+foldl f z t = appEndo (getDual (foldMap (Dual . Endo . flip f) t)) z++-- -- | since 0.1.2+foldr' :: G.Vector v a => (a -> b -> b) -> b -> CircularVector v a -> b+foldr' f z0 xs = foldl f' id xs z0+  where f' k x z = k $! f x z++-- -- | since 0.1.2+foldl' :: G.Vector v a => (b -> a -> b) -> b -> CircularVector v a -> b+foldl' f z0 xs = foldr f' id xs z0+      where f' x k z = k $! f z x++-- -- | since 0.1.2+foldr1 :: G.Vector v a => (a -> a -> a) -> CircularVector v a -> a+foldr1 f xs = fromMaybe (errorWithoutStackTrace "foldr1: empty structure")+                    (foldr mf Nothing xs)+      where+        mf x m = Just (case m of+                         Nothing -> x+                         Just y  -> f x y)++-- -- | since 0.1.2+foldl1 :: G.Vector v a => (a -> a -> a) -> CircularVector v a -> a+foldl1 f xs = fromMaybe (errorWithoutStackTrace "foldl1: empty structure")+                    (foldl mf Nothing xs)+      where+        mf m y = Just (case m of+                         Nothing -> y+                         Just x  -> f x y)++-- | since 0.1.2+toNonEmpty :: G.Vector v a => CircularVector v a -> NonEmpty a+toNonEmpty = NonEmptyList.fromList . toList++-- | Lazily-accumulating semigroupoidal fold over+--   a 'CircularVector'.+--+--   since 0.1.2+foldMap1 :: (G.Vector v a, Semigroup m) => (a -> m) -> CircularVector v a -> m+foldMap1 f = \v ->+  let len = Data.Vector.Circular.Generic.length v+      go !ix+        | ix < len-1 = f (index v ix) <> go (ix + 1)+        | otherwise  = f (last v)+  in go 0+{-# inline foldMap1 #-}++-- | Strictly-accumulating semigroupoidal fold over+--   a 'CircularVector'.+--+--   since 0.1.2+foldMap1' :: (G.Vector v a, Semigroup m) => (a -> m) -> CircularVector v a -> m+foldMap1' f = \v ->+  let len = Data.Vector.Circular.Generic.length v+      go !ix !acc+        | ix < len = go (ix + 1) (acc <> f (index v ix))+        | otherwise = acc+  in go 1 (f (head v))+{-# inline foldMap1' #-}++-- | /O(n)/ Construct a 'Vector' from a 'CircularVector'.+--+--   since 0.1.2+toVector :: G.Vector v a => CircularVector v a -> v a+toVector v = G.generate (length v) (index v)++-- | /O(n)/ Construct a 'NonEmptyVector' from a 'CircularVector'.+--+--   @since 0.1.2+toNonEmptyVector :: G.Vector v a => CircularVector v a -> NonEmptyVector a+toNonEmptyVector v = NonEmpty.generate1 (length v) (index v)++-- | /O(1)/ Construct a 'CircularVector' from a vector.+--+--   since 0.1.2+fromVector :: G.Vector v a => v a -> Maybe (CircularVector v a)+fromVector v | G.null v = Nothing+fromVector v = Just (CircularVector v 0)+{-# inline fromVector #-}++-- | /O(1)/ Construct a 'CircularVector' from a 'Vector'.+--+--   Calls @'error'@ if the input vector is empty.+--+--   since 0.1.2+unsafeFromVector :: G.Vector v a => v a -> CircularVector v a+unsafeFromVector v = CircularVector v 0++-- | /O(n)/ Convert from a circular vector to a list.+--+--+-- >>> let nev = unsafeFromList @Vector [1..3] in toList nev+-- [1,2,3]+--+--   @since 0.1.2+toList :: G.Vector v a => CircularVector v a -> [a]+toList = G.toList . toVector++-- | /O(n)/ Construct a 'CircularVector' from a list.+--+--   since 0.1.2+fromList :: G.Vector v a => [a] -> Maybe (CircularVector v a)+fromList xs = fromListN (Prelude.length xs) xs+{-# inline fromList #-}++-- | Construct a 'CircularVector' from a list with a size hint.+--+--   since 0.1.2+fromListN :: G.Vector v a => Int -> [a] -> Maybe (CircularVector v a)+fromListN n xs = fromVector (G.fromListN n xs)+{-# inline fromListN #-}++-- | /O(n)/ Construct a 'CircularVector' from a list.+--+--   Calls @'error'@ if the input list is empty.+--+--   since 0.1.2+unsafeFromList :: G.Vector v a => [a] -> CircularVector v a+unsafeFromList xs = unsafeFromListN (Prelude.length xs) xs++-- | /O(n)/ Construct a 'CircularVector' from a list with a size hint.+--+--   Calls @'error'@ if the input list is empty, or+--   if the size hint is @'<=' 0@.+--+--    since 0.1.2+unsafeFromListN :: G.Vector v a => Int -> [a] -> CircularVector v a+unsafeFromListN n xs+  | n <= 0 = error "Data.Vector.Circular.unsafeFromListN: invalid length!"+  | otherwise = unsafeFromVector (G.fromListN n xs)++-- | /O(1)/ Construct a singleton 'CircularVector.+--+--   since 0.1.2+singleton :: G.Vector v a => a -> CircularVector v a+singleton = unsafeFromVector . G.singleton+{-# inline singleton #-}++-- | /O(1)/ Index into a 'CircularVector'. This is always total.+--+--   since 0.1.2+index :: G.Vector v a => CircularVector v a -> Int -> a+index (CircularVector v r) = \ !ix ->+  let len = G.length v+  in G.unsafeIndex v (unsafeMod (ix + r) len)+{-# inline index #-}++-- | /O(1)/ Get the first element of a 'CircularVector'. This is always total.+--+--   since 0.1.2+head :: G.Vector v a => CircularVector v a -> a+head v = index v 0+{-# inline head #-}++-- | /O(1)/ Get the last element of a 'CircularVector'. This is always total.+--+--   since 0.1.2+last :: G.Vector v a => CircularVector v a -> a+last v = index v (Data.Vector.Circular.Generic.length v - 1)+{-# inline last #-}++-- | /O(1)/ Rotate the vector to left by @n@ number of elements.+--+--   /Note/: Right rotations start to break down due to+--   arithmetic overflow when the size of the input vector is+--   @'>' 'maxBound' @'Int'@+--+--   since 0.1.2+rotateRight :: G.Vector v a => Int -> CircularVector v a -> CircularVector v a+rotateRight r' (CircularVector v r) = CircularVector v h+  where+    len = G.length v+    h = unsafeMod (r + unsafeMod r' len) len+{-# inline rotateRight #-}++-- | /O(1)/ Rotate the vector to the left by @n@ number of elements.+--+--   /Note/: Left rotations start to break down due to+--   arithmetic underflow when the size of the input vector is+--   @'>' 'maxBound' @'Int'@+--+--   since 0.1.2+rotateLeft :: G.Vector v a => Int -> CircularVector v a -> CircularVector v a+rotateLeft r' (CircularVector v r) = CircularVector v h+  where+    len = G.length v+    h = unsafeMod (r - unsafeMod r' len) len+{-# inline rotateLeft #-}+{-+-- | Construct a 'CircularVector' at compile-time using+--   typed Template Haskell.+--+--   since 0.1.2+vec :: (G.Vector v a, Lift a) => [a] -> Q (TExp (CircularVector v a))+vec [] = fail "Cannot create an empty CircularVector!"+vec xs =+#if MIN_VERSION_template_haskell(2,16,0)+  liftTyped (unsafeFromList xs)+#else+  unsafeTExpCoerce [|unsafeFromList xs|]+#endif /* MIN_VERSION_template_haskell(2,16,0) */+-}+-- | since 0.1.2+equivalent :: (G.Vector v a, Eq (v a), Ord a) => CircularVector v a -> CircularVector v a -> Bool+equivalent x y = vector (canonise x) == vector (canonise y)++-- | since 0.1.2+canonise :: (G.Vector v a, Ord a) => CircularVector v a -> CircularVector v a+canonise c@(CircularVector v r) = CircularVector v' (r - lr)+  where+    lr = leastRotation (toNonEmptyVector c)+    v' = toVector (rotateRight lr (CircularVector v 0))++-- | since 0.1.2+leastRotation :: forall a. (Ord a) => NonEmptyVector a -> Int+leastRotation v = runST go+  where+    go :: forall s. ST s Int+    go = do+      let s = v <> v+      let len = NonEmpty.length s+      f <- MVector.replicate @_ @Int len (-1)+      kVar <- newMutVar @_ @Int 0+      Control.Monad.forM_ [1..len-1] $ \j -> do+        sj <- NonEmpty.indexM s j+        i0 <- readMutVar kVar >>= \k -> MVector.read f (j - k - 1)+        let loop i = do+              a <- readMutVar kVar >>= \k -> NonEmpty.indexM s (k + i + 1)+              if (i /= (-1) && sj /= a)+                then do+                  Control.Monad.when (sj < a) (writeMutVar kVar (j - i - 1))+                  loop =<< MVector.read f i+                else pure i+        i <- loop i0+        a <- readMutVar kVar >>= \k -> NonEmpty.indexM s (k + i + 1)+        if sj /= a+          then do+            readMutVar kVar >>= \k -> Control.Monad.when (sj < (s NonEmpty.! k)) (writeMutVar kVar j)+            readMutVar kVar >>= \k -> MVector.write f (j - k) (-1)+          else do+            readMutVar kVar >>= \k -> MVector.write f (j - k) (i + 1)+      readMutVar kVar++-- only safe if second argument is nonzero.+-- used internally for modulus operations with length.+unsafeMod :: Int -> Int -> Int+unsafeMod = GHC.Base.modInt+{-# inline unsafeMod #-}++-- | /O(min(m,n))/ Zip two circular vectors with the given function.+--+--   @since 0.1.2+zipWith :: (G.Vector v a, G.Vector v b, G.Vector v c) => (a -> b -> c) -> CircularVector v a -> CircularVector v b -> CircularVector v c+zipWith f a b = unsafeFromVector $ G.zipWith f (toVector a) (toVector b)++-- | Zip three circular vectors with the given function.+--+--   @since 0.1.2+zipWith3 :: (G.Vector v a, G.Vector v b, G.Vector v c, G.Vector v d) => +  (a -> b -> c -> d) -> CircularVector v a -> CircularVector v b -> CircularVector v c+  -> CircularVector v d+zipWith3 f a b c = unsafeFromVector $ G.zipWith3 f (toVector a) (toVector b) (toVector c)++-- | /O(min(n,m))/ Elementwise pairing of circular vector elements.+--   This is a special case of 'zipWith' where the function argument is '(,)'+--+--   @since 0.1.2+zip :: (G.Vector v a, G.Vector v b, G.Vector v (a,b)) => CircularVector v a -> CircularVector v b -> CircularVector v (a,b)+zip a b = unsafeFromVector $ G.zip (toVector a) (toVector b)++-- | Zip together three circular vectors.+--+--   @since 0.1.2+zip3 :: (G.Vector v a, G.Vector v b, G.Vector v c, G.Vector v (a,b,c)) =>+  CircularVector v a -> CircularVector v b -> CircularVector v c -> CircularVector v (a,b,c)+zip3 a b c = unsafeFromVector $ G.zip3 (toVector a) (toVector b) (toVector c)++-- | /O(n)/ Reverse a circular vector.+--+--   @since 0.1.2+reverse :: G.Vector v a => CircularVector v a -> CircularVector v a+reverse = unsafeFromVector . G.reverse . toVector++-- | /O(n)/ Rotate to the minimum element of the circular vector according to the+--   given comparison function.+--+--   @since 0.1.2+rotateToMinimumBy :: G.Vector v a => (a -> a -> Ordering) -> CircularVector v a -> CircularVector v a+rotateToMinimumBy f (CircularVector v _rot) =+  CircularVector v (G.minIndexBy f v)++-- | /O(n)/ Rotate to the maximum element of the circular vector according to the+--   given comparison function.+--+--   @since 0.1.2+rotateToMaximumBy :: G.Vector v a => (a -> a -> Ordering) -> CircularVector v a -> CircularVector v a+rotateToMaximumBy f (CircularVector v _rot) =+  CircularVector v (G.maxIndexBy f v)++-- | /O(n)/ Check if all elements satisfy the predicate.+--+--   @since 0.1.2+all :: G.Vector v a => (a -> Bool) -> CircularVector v a -> Bool+all f = G.all f . vector++-- | /O(n)/ Check if any element satisfies the predicate.+--+--   @since 0.1.2+any :: G.Vector v a => (a -> Bool) -> CircularVector v a -> Bool+any f = G.any f . vector++-- | /O(n)/ Check if all elements are True.+--+--   @since 0.1.2+and :: G.Vector v Bool => CircularVector v Bool -> Bool+and = G.and . vector++-- | /O(n)/ Check if any element is True.+--+--   @since 0.1.2+or :: G.Vector v Bool => CircularVector v Bool -> Bool+or = G.or . vector++-- | /O(n)/ Compute the sum of the elements.+--+--   @since 0.1.2+sum :: (G.Vector v a, Num a) => CircularVector v a -> a+sum = G.sum . vector++-- | /O(n)/ Compute the product of the elements.+--+--   @since 0.1.2+product :: (G.Vector v a, Num a) => CircularVector v a -> a+product = G.sum . vector++-- | /O(n)/ Yield the maximum element of the circular vector.+--+--   @since 0.1.2+maximum :: (G.Vector v a, Ord a) => CircularVector v a -> a+maximum = G.maximum . vector++-- | /O(n)/ Yield the maximum element of a circular vector according to the+--   given comparison function.+--+--   @since 0.1.2+maximumBy :: G.Vector v a => (a -> a -> Ordering) -> CircularVector v a -> a+maximumBy f = G.maximumBy f . vector++-- | /O(n)/ Yield the minimum element of the circular vector.+--+--   @since 0.1.2+minimum :: (G.Vector v a, Ord a) => CircularVector v a -> a+minimum = G.minimum . vector++-- | /O(n)/ Yield the minimum element of a circular vector according to the+--   given comparison function.+--+--   @since 0.1.2+minimumBy :: G.Vector v a => (a -> a -> Ordering) -> CircularVector v a -> a+minimumBy f = G.minimumBy f . vector++-- | /O(n)/ Circular vector of the given length with the same value in+-- each position.+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--   @since 0.1.2+--+-- >>> replicate @Vector 3 "a"+-- Just (CircularVector {vector = ["a","a","a"], rotation = 0})+--+-- >>> replicate @Vector 0 "a"+-- Nothing+--+replicate :: G.Vector v a => Int -> a -> Maybe (CircularVector v a)+replicate n a = fromVector (G.replicate n a)++-- | /O(n)/ Circular vector of the given length with the same value in+-- each position.+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--   @since 0.1.2+--+-- >>> toList $ replicate1 @Vector 3 "a"+-- ["a","a","a"]+--+-- >>> toList $ replicate1 @Vector 0 "a"+-- ["a"]+--+-- >>> toList $ replicate1 @Vector (-1) "a"+-- ["a"]+replicate1 :: G.Vector v a => Int -> a -> CircularVector v a+replicate1 n a = unsafeFromVector (G.replicate (max n 1) a)++-- | /O(n)/ Construct a circular vector of the given length by applying the function to+-- each index.+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--   @since 0.1.2+--+-- >>> let f 0 = "a"; f _ = "k"; f :: Int -> String+--+-- >>> generate @Vector 1 f+-- Just (CircularVector {vector = ["a"], rotation = 0})+--+-- >>> generate @Vector 0 f+-- Nothing+--+-- >>> generate @Vector 2 f+-- Just (CircularVector {vector = ["a","k"], rotation = 0})+--+generate :: G.Vector v a => Int -> (Int -> a) -> Maybe (CircularVector v a)+generate n f = fromVector (G.generate n f)++-- | /O(n)/ Construct a circular vector of the given length by applying the function to+-- each index.+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--   @since 0.1.2+--+-- >>> let f 0 = "a"; f _ = "k"; f :: Int -> String+--+-- >>> toList $ generate1 @Vector 2 f+-- ["a","k"]+--+-- >>> toList $ generate1 @Vector 0 f+-- ["a"]+--+-- >>> toList $ generate1 @Vector (-1) f+-- ["a"]+--+generate1 :: G.Vector v a => Int -> (Int -> a) -> CircularVector v a+generate1 n f = unsafeFromVector (G.generate (max n 1) f)++-- | /O(n)/ Apply function n times to value. Zeroth element is original value.+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--   @since 0.1.2+--+-- >>> iterateN @Vector 3 (+1) 0+-- Just (CircularVector {vector = [0,1,2], rotation = 0})+--+-- >>> iterateN @Vector 0 (+1) 0+-- Nothing+--+-- >>> iterateN @Vector (-1) (+1) 0+-- Nothing+--+iterateN :: G.Vector v a => Int -> (a -> a) -> a -> Maybe (CircularVector v a)+iterateN n f a = fromVector (G.iterateN n f a)++-- | /O(n)/ Apply function n times to value. Zeroth element is original value.+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--   @since 0.1.2+--+-- >>> iterateN1 @Vector 3 (+1) 0+-- CircularVector {vector = [0,1,2], rotation = 0}+--+-- >>> iterateN1 @Vector 0 (+1) 0+-- CircularVector {vector = [0], rotation = 0}+--+-- >>> iterateN1 @Vector (-1) (+1) 0+-- CircularVector {vector = [0], rotation = 0}+--+iterateN1 :: G.Vector v a => Int -> (a -> a) -> a -> CircularVector v a+iterateN1 n f a = unsafeFromVector (G.iterateN (max n 1) f a)++-- | /O(n)/ Execute the monadic action the given number of times and store+-- the results in a circular vector.+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--   @since 0.1.2+--+-- >>> replicateM @Maybe @Vector 3 (Just "a")+-- Just (Just (CircularVector {vector = ["a","a","a"], rotation = 0}))+--+-- >>> replicateM @Maybe @Vector 3 Nothing+-- Nothing+--+-- >>> replicateM @Maybe @Vector 0 (Just "a")+-- Just Nothing+--+-- >>> replicateM @Maybe @Vector (-1) (Just "a")+-- Just Nothing+--+replicateM :: (Monad m, G.Vector v a) => Int -> m a -> m (Maybe (CircularVector v a))+replicateM n a = fmap fromVector (G.replicateM n a)++-- | /O(n)/ Execute the monadic action the given number of times and store+-- the results in a circular vector.+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--   @since 0.1.2+--+-- >>> replicate1M @Maybe @Vector 3 (Just "a")+-- Just (CircularVector {vector = ["a","a","a"], rotation = 0})+--+-- >>> replicate1M @Maybe @Vector 3 Nothing+-- Nothing+--+-- >>> replicate1M @Maybe @Vector 0 (Just "a")+-- Just (CircularVector {vector = ["a"], rotation = 0})+--+-- >>> replicate1M @Maybe @Vector (-1) (Just "a")+-- Just (CircularVector {vector = ["a"], rotation = 0})+--+replicate1M :: (Monad m, G.Vector v a) => Int -> m a -> m (CircularVector v a)+replicate1M n a = fmap unsafeFromVector (G.replicateM (max n 1) a)++-- | /O(n)/ Construct a circular vector of the given length by applying the monadic+-- action to each index+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--   @since 0.1.2+--+-- >>> generateM @[] @Vector 3 (\i -> if i < 1 then ["a"] else ["b"])+-- [Just (CircularVector {vector = ["a","b","b"], rotation = 0})]+--+-- >>> generateM @[] @Vector @Int 3 (const [])+-- []+--+-- >>> generateM @[] @Vector @Int 0 (const [1])+-- [Nothing]+--+-- >>> generateM @Maybe @Vector @Int (-1) (const Nothing)+-- Just Nothing+--+generateM :: (Monad m, G.Vector v a) => Int -> (Int -> m a) -> m (Maybe (CircularVector v a))+generateM n f = fmap fromVector (G.generateM n f)++-- | /O(n)/ Construct a circular vector of the given length by applying the monadic+-- action to each index+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--   @since 0.1.2+--+-- >>> generate1M @Maybe @Vector 3 (\i -> if i < 1 then Just "a" else Just "b")+-- Just (CircularVector {vector = ["a","b","b"], rotation = 0})+--+-- >>> generate1M @[] @Vector 3 (const [])+-- []+--+-- >>> generate1M @Maybe @Vector 0 (const $ Just 1)+-- Just (CircularVector {vector = [1], rotation = 0})+--+-- >>> generate1M @Maybe @Vector (-1) (const Nothing)+-- Nothing+--+generate1M :: (Monad m, G.Vector v a) => Int -> (Int -> m a) -> m (CircularVector v a)+generate1M n f = fmap unsafeFromVector (G.generateM (max n 1) f)++-- | /O(n)/ Apply monadic function n times to value. Zeroth element is+-- original value.+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--   @since 0.1.2+--+-- >>> iterateNM @Maybe @Vector 3 return "a"+-- Just (Just (CircularVector {vector = ["a","a","a"], rotation = 0}))+--+-- >>> iterateNM @Maybe @Vector 3 (const Nothing) "a"+-- Nothing+--+-- >>> iterateNM @Maybe @Vector 0 return "a"+-- Just Nothing+--+iterateNM :: (Monad m, G.Vector v a) => Int -> (a -> m a) -> a -> m (Maybe (CircularVector v a))+iterateNM n f a = fmap fromVector (G.iterateNM n f a)++-- | /O(n)/ Apply monadic function n times to value. Zeroth element is+-- original value.+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--   @since 0.1.2+--+-- >>> iterateN1M @Maybe @Vector 3 return "a"+-- Just (CircularVector {vector = ["a","a","a"], rotation = 0})+--+-- >>> iterateN1M @Maybe @Vector 3 (const Nothing) "a"+-- Nothing+--+-- >>> iterateN1M @Maybe @Vector 0 return "a"+-- Just (CircularVector {vector = ["a"], rotation = 0})+--+-- >>> iterateN1M @Maybe @Vector (-1) return "a"+-- Just (CircularVector {vector = ["a"], rotation = 0})+--+iterateN1M :: (Monad m, G.Vector v a) => Int -> (a -> m a) -> a -> m (CircularVector v a)+iterateN1M n f a = fmap unsafeFromVector (G.iterateNM (max n 1) f a)++-- | Execute the monadic action and freeze the resulting circular vector.+--+--   @since 0.1.2+create :: G.Vector v a => (forall s. ST s (G.Mutable v s a)) -> Maybe (CircularVector v a)+create p = fromVector (G.create p)++-- | Execute the monadic action and freeze the resulting circular vector,+-- bypassing emptiness checks.+--+-- The onus is on the caller to guarantee the created vector is non-empty.+--+--   @since 0.1.2+unsafeCreate :: G.Vector v a => (forall s. ST s (G.Mutable v s a)) -> CircularVector v a+unsafeCreate p = unsafeFromVector (G.create p)++-- | Execute the monadic action and freeze the resulting circular vector.+--+--   @since 0.1.2+createT+    :: (Traversable t, G.Vector v a)+    => (forall s. ST s (t (G.Mutable v s a)))+    -> t (Maybe (CircularVector v a))+createT p = fmap fromVector (G.createT p)++-- | Execute the monadic action and freeze the resulting circular vector.+--+-- The onus is on the caller to guarantee the created vector is non-empty.+--+--   @since 0.1.2+unsafeCreateT+    :: (Traversable t, G.Vector v a)+    => (forall s. ST s (t (G.Mutable v s a)))+    -> t (CircularVector v a)+unsafeCreateT p = fmap unsafeFromVector (G.createT p)++-- | /O(n)/ Construct a circular vector by repeatedly applying the+-- generator function to a seed. The generator function yields 'Just' the+-- next element and the new seed or 'Nothing' if there are no more+-- elements.+--+-- If an unfold does not create meaningful values, 'Nothing' is+-- returned. Otherwise, 'Just' containing a circular vector is returned.+--+--   @since 0.1.2+--+-- >>> unfoldr @Vector (\b -> case b of "a" -> Just ("a", "b"); _ ->  Nothing) "a"+-- Just (CircularVector {vector = ["a"], rotation = 0})+--+-- >>> unfoldr @Vector (const Nothing) "a"+-- Nothing+--+unfoldr :: G.Vector v a => (b -> Maybe (a, b)) -> b -> Maybe (CircularVector v a)+unfoldr f b = fromVector (G.unfoldr f b)++-- | /O(n)/ Construct a circular vector by repeatedly applying the+-- generator function to a seed and a first element.+--+-- This variant of 'unfoldr' guarantees the resulting vector is non-+-- empty by supplying an initial element @a@.+--+--   @since 0.1.2+--+-- >>> unfoldr1 @Vector (\b -> case b of "a" -> Just ("a", "b"); _ ->  Nothing) "first" "a"+-- CircularVector {vector = ["first","a"], rotation = 0}+--+-- >>> unfoldr1 @Vector (const Nothing) "first" "a"+-- CircularVector {vector = ["first"], rotation = 0}+--+unfoldr1 :: G.Vector v a => (b -> Maybe (a, b)) -> a -> b -> CircularVector v a+unfoldr1 f a b = cons a (unsafeFromVector (G.unfoldr f b))++-- | /O(n)/ Construct a circular vector with at most n elements by repeatedly+-- applying the generator function to a seed. The generator function yields+-- 'Just' the next element and the new seed or 'Nothing' if there are no+-- more elements.+--+-- If an unfold does not create meaningful values, 'Nothing' is+-- returned. Otherwise, 'Just' containing a circular vector is returned.+--+--   @since 0.1.2+--+-- >>> unfoldrN @Vector 3 (\b -> Just (b+1, b+1)) 0+-- Just (CircularVector {vector = [1,2,3], rotation = 0})+--+-- >>> unfoldrN @Vector 3 (const Nothing) 0+-- Nothing+--+-- >>> unfoldrN @Vector 0 (\b -> Just (b+1, b+1)) 0+-- Nothing+--+unfoldrN :: G.Vector v a => Int -> (b -> Maybe (a, b)) -> b -> Maybe (CircularVector v a)+unfoldrN n f b = fromVector (G.unfoldrN n f b)++-- | /O(n)/ Construct a circular vector with at most n elements by repeatedly+-- applying the generator function to a seed. The generator function yields+-- 'Just' the next element and the new seed or 'Nothing' if there are no+-- more elements.+--+-- This variant of 'unfoldrN' guarantees the resulting vector is non-+-- empty by supplying an initial element @a@.+--+--   @since 0.1.2+--+-- >>> unfoldr1N @Vector 3 (\b -> Just (b+1, b+1)) 0 0+-- CircularVector {vector = [0,1,2,3], rotation = 0}+--+-- >>> unfoldr1N @Vector 3 (const Nothing) 0 0+-- CircularVector {vector = [0], rotation = 0}+--+-- >>> unfoldr1N @Vector 0 (\b -> Just (b+1, b+1)) 0 0+-- CircularVector {vector = [0], rotation = 0}+--+unfoldr1N+    :: G.Vector v a+    => Int+    -> (b -> Maybe (a, b))+    -> a+    -> b+    -> CircularVector v a+unfoldr1N n f a b = cons a (unsafeFromVector (G.unfoldrN n f b))++-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator+-- function to a seed. The generator function yields Just the next element+-- and the new seed or Nothing if there are no more elements.+--+-- If an unfold does not create meaningful values, 'Nothing' is+-- returned. Otherwise, 'Just' containing a circular vector is returned.+--+--   @since 0.1.2+unfoldrM+    :: (Monad m, G.Vector v a)+    => (b -> m (Maybe (a, b)))+    -> b+    -> m (Maybe (CircularVector v a))+unfoldrM f b = fmap fromVector (G.unfoldrM f b)++-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator+-- function to a seed. The generator function yields Just the next element+-- and the new seed or Nothing if there are no more elements.+--+-- This variant of 'unfoldrM' guarantees the resulting vector is non-+-- empty by supplying an initial element @a@.+--+--   @since 0.1.2+unfoldr1M+    :: (Monad m, G.Vector v a)+    => (b -> m (Maybe (a, b)))+    -> a+    -> b+    -> m (CircularVector v a)+unfoldr1M f a b = fmap (cons a . unsafeFromVector) (G.unfoldrM f b)++-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator+-- function to a seed. The generator function yields Just the next element and+-- the new seed or Nothing if there are no more elements.+--+-- If an unfold does not create meaningful values, 'Nothing' is+-- returned. Otherwise, 'Just' containing a circular vector is returned.+--+--   @since 0.1.2+unfoldrNM+    :: (Monad m, G.Vector v a)+    => Int+    -> (b -> m (Maybe (a, b)))+    -> b+    -> m (Maybe (CircularVector v a))+unfoldrNM n f b = fmap fromVector (G.unfoldrNM n f b)++-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator+-- function to a seed. The generator function yields Just the next element and+-- the new seed or Nothing if there are no more elements.+--+-- This variant of 'unfoldrNM' guarantees the resulting vector is non-+-- empty by supplying an initial element @a@.+--+--   @since 0.1.2+unfoldr1NM+    :: (Monad m, G.Vector v a)+    => Int+    -> (b -> m (Maybe (a, b)))+    -> a+    -> b+    -> m (CircularVector v a)+unfoldr1NM n f a b = fmap (cons a . unsafeFromVector) (G.unfoldrNM n f b)++-- | /O(n)/ Construct a circular vector with n elements by repeatedly applying the+-- generator function to the already constructed part of the vector.+--+-- If 'constructN' does not create meaningful values, 'Nothing' is+-- returned. Otherwise, 'Just' containing a circular vector is returned.+--+--   @since 0.1.2+constructN :: G.Vector v a => Int -> (v a -> a) -> Maybe (CircularVector v a)+constructN n f = fromVector (G.constructN n f)++-- | /O(n)/ Construct a circular vector with n elements from right to left by repeatedly+-- applying the generator function to the already constructed part of the vector.+--+-- If 'constructrN' does not create meaningful values, 'Nothing' is+-- returned. Otherwise, 'Just' containing a circular vector is returned.+--+--   @since 0.1.2+constructrN :: G.Vector v a => Int -> (v a -> a) -> Maybe (CircularVector v a)+constructrN n f = fromVector (G.constructrN n f)++-- | /O(n)/ Yield a circular vector of the given length containing the+-- values x, x+1 etc. This operation is usually more efficient than+-- 'enumFromTo'.+--+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,+-- otherwise, 'Just' containing a circular vector.+--+--   @since 0.1.2+enumFromN :: (G.Vector v a, Num a) => a -> Int -> Maybe (CircularVector v a)+enumFromN a n = fromVector (G.enumFromN a n)++-- | /O(n)/ Yield a circular vector of length @max n 1@ containing the+-- values x, x+1 etc. This operation is usually more efficient than+-- 'enumFromTo'.+--+--   @since 0.1.2+enumFromN1 :: (G.Vector v a, Num a) => a -> Int -> CircularVector v a+enumFromN1 a n = unsafeFromVector (G.enumFromN a (max n 1))++-- | /O(n)/ Yield a circular vector of the given length containing the+-- values x, x+y, x+y+y etc. This operations is usually more efficient than+-- 'enumFromThenTo'.+--+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,+-- otherwise, 'Just' containing a circular vector.+--+--   @since 0.1.2+enumFromStepN :: (G.Vector v a, Num a) => a -> a -> Int -> Maybe (CircularVector v a)+enumFromStepN a0 a1 n = fromVector (G.enumFromStepN a0 a1 n)++-- | /O(n)/ Yield a circular vector of length @max n 1@ containing the+-- values x, x+y, x+y+y etc. This operations is usually more efficient than+-- 'enumFromThenTo'.+--+--   @since 0.1.2+enumFromStepN1 :: (G.Vector v a, Num a) => a -> a -> Int -> CircularVector v a+enumFromStepN1 a0 a1 n = unsafeFromVector (G.enumFromStepN a0 a1 (max n 1))++-- | /O(n)/ Enumerate values from x to y.+--+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,+-- otherwise, 'Just' containing a circular vector.+--+-- /WARNING/: This operation can be very inefficient. If at all possible,+-- use 'enumFromN' instead.+--+--+--   @since 0.1.2+enumFromTo :: (G.Vector v a, Enum a) => a -> a -> Maybe (CircularVector v a)+enumFromTo a0 a1 = fromVector (G.enumFromTo a0 a1)++-- | /O(n)/ Enumerate values from x to y with a specific step z.+--+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,+-- otherwise, 'Just' containing a circular vector.+--+-- /WARNING/: This operation can be very inefficient. If at all possible,+-- use 'enumFromStepN' instead.+--+--   @since 0.1.2+enumFromThenTo :: (G.Vector v a, Enum a) => a -> a -> a -> Maybe (CircularVector v a)+enumFromThenTo a0 a1 a2 = fromVector (G.enumFromThenTo a0 a1 a2)++-- | /O(n)/ Prepend an element+--+--   @since 0.1.2+--+-- >>> cons 1 (unsafeFromList @Vector [2,3])+-- CircularVector {vector = [1,2,3], rotation = 0}+--+cons :: G.Vector v a => a -> CircularVector v a -> CircularVector v a+cons a cv = consV a (toVector cv)+{-# INLINE cons #-}++-- | /O(n)/ Prepend an element to a Vector+--+--   @since 0.1.2+--+-- >>> consV 1 (Data.Vector.fromList [2,3])+-- CircularVector {vector = [1,2,3], rotation = 0}+--+consV :: G.Vector v a => a -> v a -> CircularVector v a+consV a = unsafeFromVector . G.cons a+{-# INLINE consV #-}++-- | /O(n)/ Append an element+--+--   @since 0.1.2+--+-- >>> snoc (unsafeFromList @Vector [1,2]) 3+-- CircularVector {vector = [1,2,3], rotation = 0}+--+snoc :: G.Vector v a => CircularVector v a -> a -> CircularVector v a+snoc = snocV . toVector++-- | /O(n)/ Append an element to a Vector+--+--   @since 0.1.2+--+-- >>> snocV (Data.Vector.fromList [1,2]) 3+-- CircularVector {vector = [1,2,3], rotation = 0}+--+snocV :: G.Vector v a => v a -> a -> CircularVector v a+snocV as = unsafeFromVector . G.snoc as++-- | /O(m+n)/ Concatenate two circular vectors+--+--   @since 0.1.2+--+-- >>> (unsafeFromList @Vector [1..3]) ++ (unsafeFromList [4..6])+-- CircularVector {vector = [1,2,3,4,5,6], rotation = 0}+--+(++) :: G.Vector v a => CircularVector v a -> CircularVector v a -> CircularVector v a+v ++ v' = unsafeFromVector (toVector v G.++ toVector v')++-- | /O(n)/ Concatenate all circular vectors in the list+--+-- If list is empty, 'Nothing' is returned, otherwise 'Just'+-- containing the concatenated circular vectors+--+--   @since 0.1.2+--+-- >>> concat [(unsafeFromList @Vector [1..3]), (unsafeFromList [4..6])]+-- Just (CircularVector {vector = [1,2,3,4,5,6], rotation = 0})+--+concat :: G.Vector v a => [CircularVector v a] -> Maybe (CircularVector v a)+concat [] = Nothing+concat (a:as) = Just (concat1 (a :| as))+{-# INLINE concat #-}++-- | O(n) Concatenate all circular vectors in a non-empty list.+--+--   @since 0.1.2+--+-- >>> concat1 ((unsafeFromList @Vector [1..3]) :| [(unsafeFromList [4..6])])+-- CircularVector {vector = [1,2,3,4,5,6], rotation = 0}+--+concat1 :: G.Vector v a => NonEmpty (CircularVector v a) -> CircularVector v a+concat1 = unsafeFromVector . G.concatNE . fmap toVector++-- | /O(n)/ Map a function over a circular vector.+--+--   @since 0.1.2+--+-- >>> map (+1) $ unsafeFromList @Vector [1..3]+-- CircularVector {vector = [2,3,4], rotation = 0}+--+map :: (G.Vector v a, G.Vector v b) => (a -> b) -> CircularVector v a -> CircularVector v b+map f (CircularVector v rot) = CircularVector (G.map f v) rot++-- | /O(n)/ Apply a function to every element of a circular vector and+-- its index.+--+--   @since 0.1.2+--+-- >>> imap (\i a -> if i == 2 then a+1 else a+0) $ unsafeFromList @Vector [1..3]+-- CircularVector {vector = [1,2,4], rotation = 0}+--+imap :: (G.Vector v a, G.Vector v b) => (Int -> a -> b) -> CircularVector v a -> CircularVector v b+imap f = unsafeFromVector . G.imap f . toVector++-- | Map a function over a circular vector and concatenate the results.+--+--   @since 0.1.2+--+-- >>> concatMap (\a -> unsafeFromList @Vector [a,a]) (unsafeFromList [1,2,3])+-- CircularVector {vector = [1,1,2,2,3,3], rotation = 0}+--+concatMap+    :: (G.Vector v a, G.Vector v b)+    => (a -> CircularVector v b)+    -> CircularVector v a+    -> CircularVector v b+concatMap f = unsafeFromVector . G.concatMap (toVector . f) . toVector++-- | /O(n)/ Apply the monadic action to all elements of the circular+-- vector, yielding circular vector of results.+--+--   @since 0.1.2+--+-- >>> mapM Just (unsafeFromList @Vector [1..3])+-- Just (CircularVector {vector = [1,2,3], rotation = 0})+--+-- >>> mapM (const Nothing) (unsafeFromList @Vector [1..3])+-- Nothing+--+mapM :: (Monad m, G.Vector v a, G.Vector v b) => (a -> m b) -> CircularVector v a -> m (CircularVector v b)+mapM f = fmap unsafeFromVector . G.mapM f . toVector++-- | /O(n)/ Apply the monadic action to every element of a circular+-- vector and its index, yielding a circular vector of results.+--+--   @since 0.1.2+--+-- >>> imapM (\i a -> if i == 1 then Just a else Just 0) (unsafeFromList @Vector [1..3])+-- Just (CircularVector {vector = [0,2,0], rotation = 0})+--+-- >>> imapM (\_ _ -> Nothing) (unsafeFromList @Vector [1..3])+-- Nothing+--+imapM+    :: (Monad m, G.Vector v a, G.Vector v b)+    => (Int -> a -> m b)+    -> CircularVector v a+    -> m (CircularVector v b)+imapM f = fmap unsafeFromVector . G.imapM f . toVector++-- | /O(n)/ Apply the monadic action to all elements of a circular vector+-- and ignore the results.+--+--   @since 0.1.2+--+-- >>> mapM_ (const $ Just ()) (unsafeFromList @Vector [1..3])+-- Just ()+--+-- >>> mapM_ (const Nothing) (unsafeFromList @Vector [1..3])+-- Nothing+--+mapM_ :: (Monad m, G.Vector v a, G.Vector v b) => (a -> m b) -> CircularVector v a -> m ()+mapM_ f = G.mapM_ f . toVector++-- | /O(n)/ Apply the monadic action to every element of a circular+-- vector and its index, ignoring the results+--+--   @since 0.1.2+--+-- >>> imapM_ (\i a -> if i == 1 then print a else putStrLn "0") (unsafeFromList @Vector [1..3])+-- 0+-- 2+-- 0+--+-- >>> imapM_ (\_ _ -> Nothing) (unsafeFromList @Vector [1..3])+-- Nothing+--+imapM_ :: (Monad m, G.Vector v a) => (Int -> a -> m b) -> CircularVector v a -> m ()+imapM_ f = G.imapM_ f . toVector++-- | /O(n)/ Apply the monadic action to all elements of the circular+-- vector, yielding a circular vector of results.+--+-- Equivalent to @flip 'mapM'@.+--+--   @since 0.1.2+forM :: (Monad m, G.Vector v a, G.Vector v b) => CircularVector v a -> (a -> m b) -> m (CircularVector v b)+forM cv f = unsafeFromVector <$> G.forM (toVector cv) f++-- | /O(n)/ Apply the monadic action to all elements of a circular+-- vector and ignore the results.+--+-- Equivalent to @flip 'mapM_'@.+--+--   @since 0.1.2+forM_ :: (Monad m, G.Vector v a) => CircularVector v a -> (a -> m b) -> m ()+forM_ cv f = G.forM_ (toVector cv) f++-- | /O(n)/ Drop repeated adjacent elements.+--+-- >>> toList $ uniq $ unsafeFromList @Vector [1,1,2,2,3,3,1]+-- [1,2,3]+--+-- >>> toList $ uniq $ unsafeFromList @Vector [1,2,3,1]+-- [1,2,3]+uniq :: (G.Vector v a, Eq a) => CircularVector v a -> CircularVector v a+uniq = unsafeFromVector . trim . G.uniq . toVector+  where+    trim v+      | G.length v == 1 || G.head v /= G.last v+        = v+      | otherwise+        = trim (G.unsafeInit v)++-- | /O(n)/ Drop elements when predicate returns Nothing+--+-- If no elements satisfy the predicate, the resulting vector may be empty.+--+--   @since 0.1.2+--+-- >>> mapMaybe (\a -> if a == 2 then Nothing else Just a) (unsafeFromList @Vector [1..3])+-- [1,3]+mapMaybe+    :: (G.Vector v a, G.Vector v b)+    => (a -> Maybe b)+    -> CircularVector v a+    -> v b+mapMaybe f = G.mapMaybe f . toVector++-- | /O(n)/ Drop elements when predicate, applied to index and value, returns Nothing+--+-- If no elements satisfy the predicate, the resulting vector may be empty.+--+--   @since 0.1.2+--+-- >>> imapMaybe (\i a -> if a == 2 || i == 2 then Nothing else Just a) (unsafeFromList @Vector [1..3])+-- [1]+--+imapMaybe+    :: (G.Vector v a, G.Vector v b)+    => (Int -> a -> Maybe b)+    -> CircularVector v a+    -> v b+imapMaybe f = G.imapMaybe f . toVector++-- | /O(n)/ Yield the longest prefix of elements satisfying the predicate+-- without copying.+--+-- If no elements satisfy the predicate, the resulting vector may be empty.+--+--   @since 0.1.2+--+-- >>> takeWhile (/= 3) (unsafeFromList @Vector [1..3])+-- [1,2]+--+takeWhile :: G.Vector v a => (a -> Bool) -> CircularVector v a -> v a+takeWhile f = G.takeWhile f . toVector++-- | /O(n)/ Drop the longest prefix of elements that satisfy the predicate+-- without copying.+--+-- If all elements satisfy the predicate, the resulting vector may be empty.+--+--   @since 0.1.2+--+-- >>> dropWhile (/= 3) (unsafeFromList @Vector [1..3])+-- [3]+--+dropWhile :: G.Vector v a => (a -> Bool) -> CircularVector v a -> v a+dropWhile f = G.dropWhile f . toVector++-- | /O(n)/ Split the circular vector in two parts, the first one+-- containing those elements that satisfy the predicate and the second+-- one those that don't. The relative order of the elements is preserved+-- at the cost of a sometimes reduced performance compared to+-- 'unstablePartition'.+--+-- If all or no elements satisfy the predicate, one of the resulting vectors+-- may be empty.+--+--   @since 0.1.2+--+-- >>> partition (< 3) (unsafeFromList @Vector [1..5])+-- ([1,2],[3,4,5])+--+partition :: G.Vector v a => (a -> Bool) -> CircularVector v a -> (v a, v a)+partition f = G.partition f . toVector++-- | /O(n)/ Split the circular vector in two parts, the first one+-- containing those elements that satisfy the predicate and the second+-- one those that don't. The order of the elements is not preserved but+-- the operation is often faster than 'partition'.+--+-- If all or no elements satisfy the predicate, one of the resulting vectors+-- may be empty.+--+--   @since 0.1.2+unstablePartition+    :: G.Vector v a+    => (a -> Bool)+    -> CircularVector v a+    -> (v a, v a)+unstablePartition f = G.unstablePartition f . toVector++-- | /O(n)/ Split the circular vector into the longest prefix of elements+-- that satisfy the predicate and the rest without copying.+--+-- If all or no elements satisfy the predicate, one of the resulting vectors+-- may be empty.+--+--   @since 0.1.2+--+-- >>> span (== 1) (unsafeFromList @Vector [1,1,2,3,1])+-- ([1,1],[2,3,1])+--+span :: G.Vector v a => (a -> Bool) -> CircularVector v a -> (v a, v a)+span f = G.span f . toVector++-- | /O(n)/ Split the circular vector into the longest prefix of elements that do not+-- satisfy the predicate and the rest without copying.+--+-- If all or no elements satisfy the predicate, one of the resulting vectors+-- may be empty.+--+--   @since 0.1.2+--+-- >>> break (== 2) (unsafeFromList @Vector [1,1,2,3,1])+-- ([1,1],[2,3,1])+--+break :: G.Vector v a => (a -> Bool) -> CircularVector v a -> (v a, v a)+break f = G.break f . toVector++-- | /O(n)/ Check if the circular vector contains an element+--+--   @since 0.1.2+--+-- >>> elem 1 $ unsafeFromList @Vector [1..3]+-- True+-- >>> elem 4 $ unsafeFromList @Vector [1..3]+-- False+--+elem :: (G.Vector v a, Eq a) => a -> CircularVector v a -> Bool+elem a = G.elem a . toVector++-- | /O(n)/ Check if the circular vector does not contain an element+-- (inverse of 'elem')+--+--   @since 0.1.2+--+-- >>> notElem 1 $ unsafeFromList @Vector [1..3]+-- False+--+-- >>> notElem 4 $ unsafeFromList @Vector [1..3]+-- True+--+notElem :: (G.Vector v a, Eq a) => a -> CircularVector v a -> Bool+notElem a = G.notElem a . toVector++-- | /O(n)/ Yield 'Just' the first element matching the predicate or+-- 'Nothing' if no such element exists.+--+--   @since 0.1.2+--+-- >>> find (< 2) $ unsafeFromList @Vector [1..3]+-- Just 1+--+-- >>> find (< 0) $ unsafeFromList @Vector [1..3]+-- Nothing+--+find :: G.Vector v a => (a -> Bool) -> CircularVector v a -> Maybe a+find f = G.find f . toVector++-- | /O(n)/ Yield 'Just' the index of the first element matching the+-- predicate or 'Nothing' if no such element exists.+--+--   @since 0.1.2+--+-- >>> findIndex (< 2) $ unsafeFromList @Vector [1..3]+-- Just 0+--+-- >>> findIndex (< 0) $ unsafeFromList @Vector [1..3]+-- Nothing+--+-- >>> findIndex (==1) $ rotateRight 1 (unsafeFromList @Vector [1..3])+-- Just 2+findIndex :: G.Vector v a => (a -> Bool) -> CircularVector v a -> Maybe Int+findIndex f = G.findIndex f . toVector++-- | /O(n)/ Yield the indices of elements satisfying the predicate in+-- ascending order.+--+--   @since 0.1.2+--+-- >>> findIndices (< 3) $ unsafeFromList @Vector [1..3]+-- [0,1]+--+-- >>> findIndices (< 0) $ unsafeFromList @Vector [1..3]+-- []+--+findIndices :: (G.Vector v a, G.Vector v Int) => (a -> Bool) -> CircularVector v a -> v Int+findIndices f = G.findIndices f . toVector++-- | /O(n)/ Yield 'Just' the index of the first occurence of the given+-- element or 'Nothing' if the circular vector does not contain the+-- element. This is a specialised version of 'findIndex'.+--+--   @since 0.1.2+--+-- >>> elemIndex 1 $ unsafeFromList @Vector [1..3]+-- Just 0+--+-- >>> elemIndex 0 $ unsafeFromList @Vector [1..3]+-- Nothing+--+elemIndex :: (G.Vector v a, Eq a) => a -> CircularVector v a -> Maybe Int+elemIndex a = G.elemIndex a . toVector++-- | /O(n)/ Yield the indices of all occurences of the given element in+-- ascending order. This is a specialised version of 'findIndices'.+--+--   @since 0.1.2+--+-- >>> elemIndices 1 $ unsafeFromList @Vector [1,2,3,1]+-- [0,3]+--+-- >>> elemIndices 0 $ unsafeFromList @Vector [1..3]+-- []+--+elemIndices :: (G.Vector v a, G.Vector v Int, Eq a) => a -> CircularVector v a -> v Int+elemIndices a = G.elemIndices a . toVector++-- | /O(n)/ Drop elements that do not satisfy the predicate which is+-- applied to values and their indices.+--+-- If no elements satisfy the predicate, the resulting vector may be empty.+--+--   @since 0.1.2+--+-- >>> ifilter (\i a -> if a == 2 || i == 0 then False else True) (unsafeFromList @Vector [1..3])+-- [3]+--+-- >>> ifilter (\_ _ -> False) (unsafeFromList @Vector [1..3])+-- []+--+ifilter+    :: G.Vector v a+    => (Int -> a -> Bool)+    -> CircularVector v a+    -> v a+ifilter f = G.ifilter f . toVector++-- | /O(n)/ Drop elements that do not satisfy the monadic predicate.+--+-- If no elements satisfy the predicate, the resulting vector may be empty.+--+--   @since 0.1.2+--+-- >>> filterM (\a -> if a == 2 then Just False else Just True) (unsafeFromList @Vector [1..3])+-- Just [1,3]+--+-- >>> filterM (\a -> if a == 2 then Nothing else Just True) (unsafeFromList @Vector [1..3])+-- Nothing+--+-- >>> filterM (const $ Just False) (unsafeFromList @Vector [1..3])+-- Just []+--+filterM+    :: (Monad m, G.Vector v a)+    => (a -> m Bool)+    -> CircularVector v a+    -> m (v a)+filterM f = G.filterM f . toVector++-- -- | /O(n)/ Drop elements that do not satisfy the monadic predicate that is+-- -- a function of index and value.+-- --+-- -- If no elements satisfy the predicate, the resulting vector may be empty.+-- --+-- --   @since 0.1.2+-- --+-- -- >>> ifilterM (\i a -> if a == 2 || i == 0 then Just False else Just True) (unsafeFromList @Vector [1..3])+-- -- Just [3]+-- --+-- -- >>> ifilterM (\i a -> if a == 2 || i == 0 then Nothing else Just True) (unsafeFromList @Vector [1..3])+-- -- Nothing+-- --+-- -- >>> ifilterM (\_ _ -> Just False) (unsafeFromList @Vector [1..3])+-- -- Just []+-- --+-- ifilterM+--     :: (Monad m, G.Vector v a)+--     => (Int -> a -> m Bool)+--     -> CircularVector v a+--     -> m (Vector a)+-- ifilterM f = G.ifilterM f . toVector++-- | /O(n)/ Yield the circular vector obtained by replacing each element+-- @i@ of the circular index vector by @xs'!'i@. This is equivalent to+-- @'map' (xs'!') is@ but is often much more efficient.+--+--   @since 0.1.2+--+-- >>> toList $ backpermute @Vector (unsafeFromList @Vector [1..3]) (unsafeFromList @Vector [2,0])+-- [3,1]+--+backpermute :: (G.Vector v a, G.Vector v Int) =>+  CircularVector v a -> CircularVector v Int -> CircularVector v a+backpermute v i = unsafeFromVector $ G.backpermute (toVector v) (toVector i)++-- | Same as 'backpermute' but without bounds checking.+--+--   @since 0.1.2+unsafeBackpermute+    :: (G.Vector v a, G.Vector v Int)+    => CircularVector v a+    -> CircularVector v Int+    -> CircularVector v a+unsafeBackpermute v i = unsafeFromVector (G.unsafeBackpermute (toVector v) (toVector i))++-- | Apply a destructive operation to a circular vector. The operation+-- will be performed in place if it is safe to do so and will modify a+-- copy of the circular vector otherwise.+--+--   @since 0.1.2+modify+    :: G.Vector v a+    => (forall s. G.Mutable v s a -> ST s ())+    -> CircularVector v a+    -> CircularVector v a+modify p = unsafeFromVector . G.modify p . toVector
+ test/doctests.hs view
@@ -0,0 +1,34 @@+module Main (main) where++import Test.DocTest+++main :: IO ()+main = doctest $ ["-isrc" ] ++ ghcExts ++ files+++ghcExts :: [String]+ghcExts = map ("-X" ++)+          [ "Haskell2010"+          , "TypeApplications"+          ]++files :: [String]+files = map toFile modules+++toFile :: String -> String+toFile = (\s -> "src/" <> s <> ".hs") . replace '.' '/'++replace     :: Eq a => a -> a -> [a] -> [a]+replace a b = go+  where+    go []                 = []+    go (c:cs) | c == a    = b:go cs+              | otherwise = c:go cs++modules :: [String]+modules =+  [ "Data.Vector.Circular"+  , "Data.Vector.Circular.Generic"+  ]
vector-circular.cabal view
@@ -2,7 +2,7 @@ name:   vector-circular version:-  0.1.1+  0.1.2 synopsis:   circular vectors description:@@ -30,6 +30,7 @@     src   exposed-modules:     Data.Vector.Circular+    Data.Vector.Circular.Generic   build-depends:     , base >= 4.11 && < 4.17     , nonempty-vector >= 0.2 && < 0.3@@ -58,6 +59,19 @@     , hedgehog-classes   default-language:     Haskell2010++test-suite doctests+  if os(windows)+    buildable:    False+  type:           exitcode-stdio-1.0+  ghc-options:    -threaded+  hs-source-dirs: test+  main-is:        doctests.hs+  build-depends:  base+                , doctest             >= 0.8++  default-language:    Haskell2010+  source-repository head   type: