{-# language
    BangPatterns
  , CPP
  , DeriveAnyClass
  , DeriveFunctor
  , DeriveGeneric
  , DerivingStrategies
  , InstanceSigs
  , 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
  { CircularVector a -> NonEmptyVector a
vector :: {-# UNPACK #-} !(NonEmptyVector a)
  , CircularVector a -> Int
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 :: (a -> f b) -> CircularVector a -> f (CircularVector b)
traverse a -> f b
f (CircularVector NonEmptyVector a
v Int
rot) =
    NonEmptyVector b -> Int -> CircularVector b
forall a. NonEmptyVector a -> Int -> CircularVector a
CircularVector (NonEmptyVector b -> Int -> CircularVector b)
-> f (NonEmptyVector b) -> f (Int -> CircularVector b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a -> f b) -> NonEmptyVector a -> f (NonEmptyVector b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f NonEmptyVector a
v f (Int -> CircularVector b) -> f Int -> f (CircularVector b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> f Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
rot

-- | @since 0.1
instance Eq a => Eq (CircularVector a) where
  (==) :: CircularVector a -> CircularVector a -> Bool
  c0 :: CircularVector a
c0@(CircularVector NonEmptyVector a
x Int
rx) == :: CircularVector a -> CircularVector a -> Bool
== c1 :: CircularVector a
c1@(CircularVector NonEmptyVector a
y Int
ry)
    | NonEmptyVector a -> Int
forall a. NonEmptyVector a -> Int
NonEmpty.length NonEmptyVector a
x Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= NonEmptyVector a -> Int
forall a. NonEmptyVector a -> Int
NonEmpty.length NonEmptyVector a
y = Bool
False
    | Int
rx Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
ry = NonEmptyVector a
x NonEmptyVector a -> NonEmptyVector a -> Bool
forall a. Eq a => a -> a -> Bool
== NonEmptyVector a
y
    | Bool
otherwise = All -> Bool
getAll (All -> Bool) -> All -> Bool
forall a b. (a -> b) -> a -> b
$ ((Int -> All) -> [Int] -> All) -> [Int] -> (Int -> All) -> All
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Int -> All) -> [Int] -> All
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
Prelude.foldMap [Int
0..NonEmptyVector a -> Int
forall a. NonEmptyVector a -> Int
NonEmpty.length NonEmptyVector a
xInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1] ((Int -> All) -> All) -> (Int -> All) -> All
forall a b. (a -> b) -> a -> b
$ \Int
i -> Bool -> All
All (CircularVector a -> Int -> a
forall a. CircularVector a -> Int -> a
index CircularVector a
c0 Int
i a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== CircularVector a -> Int -> a
forall a. CircularVector a -> Int -> a
index CircularVector a
c1 Int
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
  CircularVector a
lhs <> :: CircularVector a -> CircularVector a -> CircularVector a
<> CircularVector a
rhs = NonEmptyVector a -> Int -> CircularVector a
forall a. NonEmptyVector a -> Int -> CircularVector a
CircularVector NonEmptyVector a
v Int
0
    where
      szLhs :: Int
szLhs = CircularVector a -> Int
forall a. CircularVector a -> Int
length CircularVector a
lhs
      szRhs :: Int
szRhs = CircularVector a -> Int
forall a. CircularVector a -> Int
length CircularVector a
rhs
      sz :: Int
sz = Int
szLhs Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
szRhs
      v :: NonEmptyVector a
v = Vector a -> NonEmptyVector a
forall a. Vector a -> NonEmptyVector a
NonEmpty.unsafeFromVector
            (Vector a -> NonEmptyVector a) -> Vector a -> NonEmptyVector a
forall a b. (a -> b) -> a -> b
$ Int -> (Int -> a) -> Vector a
forall a. Int -> (Int -> a) -> Vector a
Vector.generate Int
sz
            ((Int -> a) -> Vector a) -> (Int -> a) -> Vector a
forall a b. (a -> b) -> a -> b
$ \Int
ix -> if Int
ix Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
szLhs
                then CircularVector a -> Int -> a
forall a. CircularVector a -> Int -> a
index CircularVector a
lhs Int
ix
                else CircularVector a -> Int -> a
forall a. CircularVector a -> Int -> a
index CircularVector a
rhs (Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
szLhs)
  {-# inline (<>) #-}

-- | @since 0.1
instance Foldable CircularVector where
  foldMap :: Monoid m => (a -> m) -> CircularVector a -> m
  foldMap :: (a -> m) -> CircularVector a -> m
foldMap = (a -> m) -> CircularVector a -> m
forall m a. Monoid m => (a -> m) -> CircularVector a -> m
Data.Vector.Circular.foldMap
  {-# inline foldMap #-}

#if MIN_VERSION_base(4,13,0)
  foldMap' :: Monoid m => (a -> m) -> CircularVector a -> m
  foldMap' :: (a -> m) -> CircularVector a -> m
foldMap' = (a -> m) -> CircularVector a -> m
forall m a. Monoid m => (a -> m) -> CircularVector a -> m
Data.Vector.Circular.foldMap'
  {-# inline foldMap' #-}
#endif /* MIN_VERSION_base(4,13,0) */

  null :: CircularVector a -> Bool
  null :: CircularVector a -> Bool
null CircularVector a
_ = Bool
False -- nonempty structure is always not null
  {-# inline null #-}

  length :: CircularVector a -> Int
  length :: CircularVector a -> Int
length = CircularVector a -> Int
forall a. CircularVector a -> Int
Data.Vector.Circular.length
  {-# inline length #-}

-- | @since 0.1
instance Foldable1 CircularVector where
  foldMap1 :: Semigroup m => (a -> m) -> CircularVector a -> m
  foldMap1 :: (a -> m) -> CircularVector a -> m
foldMap1 = (a -> m) -> CircularVector a -> m
forall m a. Semigroup m => (a -> m) -> CircularVector a -> m
Data.Vector.Circular.foldMap1
  {-# inline foldMap1 #-}

-- | @since 0.1
instance Lift a => Lift (CircularVector a) where
  lift :: CircularVector a -> Q Exp
lift CircularVector a
c = do
    Exp
v <- [|NonEmpty.toVector (vector c)|]
    Exp
r <- [|rotation c|]
    Exp -> Q Exp
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Exp -> Q Exp) -> Exp -> Q Exp
forall a b. (a -> b) -> a -> b
$ Name -> Exp
ConE ''CircularVector
      Exp -> Exp -> Exp
`AppE` (Name -> Exp
VarE 'NonEmpty.unsafeFromVector Exp -> Exp -> Exp
`AppE` Exp
v)
      Exp -> Exp -> Exp
`AppE` Exp
r
#if MIN_VERSION_template_haskell(2,16,0)
  liftTyped :: CircularVector a -> Q (TExp (CircularVector a))
liftTyped = Q Exp -> Q (TExp (CircularVector a))
forall a. Q Exp -> Q (TExp a)
unsafeTExpCoerce (Q Exp -> Q (TExp (CircularVector a)))
-> (CircularVector a -> Q Exp)
-> CircularVector a
-> Q (TExp (CircularVector a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CircularVector a -> Q Exp
forall t. Lift t => t -> Q Exp
lift
#endif /* MIN_VERSION_template_haskell(2,16,0) */

-- | Get the length of a 'CircularVector'.
--
--   @since 0.1
length :: CircularVector a -> Int
length :: CircularVector a -> Int
length (CircularVector NonEmptyVector a
v Int
_) = NonEmptyVector a -> Int
forall a. NonEmptyVector a -> Int
NonEmpty.length NonEmptyVector a
v
{-# inline length #-}

-- | Lazily-accumulating monoidal fold over a 'CircularVector'.
--   @since 0.1
foldMap :: Monoid m => (a -> m) -> CircularVector a -> m
foldMap :: (a -> m) -> CircularVector a -> m
foldMap a -> m
f = \CircularVector a
v ->
  let len :: Int
len = CircularVector a -> Int
forall a. CircularVector a -> Int
Data.Vector.Circular.length CircularVector a
v
      go :: Int -> m
go !Int
ix
        | Int
ix Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len = a -> m
f (CircularVector a -> Int -> a
forall a. CircularVector a -> Int -> a
index CircularVector a
v Int
ix) m -> m -> m
forall a. Semigroup a => a -> a -> a
<> Int -> m
go (Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
        | Bool
otherwise = m
forall a. Monoid a => a
mempty
  in Int -> m
go Int
0
{-# inline foldMap #-}

-- | Strictly-accumulating monoidal fold over a 'CircularVector'.
--
--   @since 0.1
foldMap' :: Monoid m => (a -> m) -> CircularVector a -> m
foldMap' :: (a -> m) -> CircularVector a -> m
foldMap' a -> m
f = \CircularVector a
v ->
  let len :: Int
len = CircularVector a -> Int
forall a. CircularVector a -> Int
Data.Vector.Circular.length CircularVector a
v
      go :: Int -> m -> m
go !Int
ix !m
acc
        | Int
ix Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len = Int -> m -> m
go (Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) (m
acc m -> m -> m
forall a. Semigroup a => a -> a -> a
<> a -> m
f (CircularVector a -> Int -> a
forall a. CircularVector a -> Int -> a
index CircularVector a
v Int
ix))
        | Bool
otherwise = m
acc
  in Int -> m -> m
go Int
0 m
forall a. Monoid a => a
mempty
{-# inline foldMap' #-}

-- | @since 0.1
foldr :: (a -> b -> b) -> b -> CircularVector a -> b
foldr :: (a -> b -> b) -> b -> CircularVector a -> b
foldr = (a -> b -> b) -> b -> CircularVector a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
Foldable.foldr

-- | @since 0.1
foldl :: (b -> a -> b) -> b -> CircularVector a -> b
foldl :: (b -> a -> b) -> b -> CircularVector a -> b
foldl = (b -> a -> b) -> b -> CircularVector a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
Foldable.foldl

-- | @since 0.1
foldr' :: (a -> b -> b) -> b -> CircularVector a -> b
foldr' :: (a -> b -> b) -> b -> CircularVector a -> b
foldr' = (a -> b -> b) -> b -> CircularVector a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
Foldable.foldr'

-- | @since 0.1
foldl' :: (b -> a -> b) -> b -> CircularVector a -> b
foldl' :: (b -> a -> b) -> b -> CircularVector a -> b
foldl' = (b -> a -> b) -> b -> CircularVector a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
Foldable.foldl'

-- | @since 0.1
foldr1 :: (a -> a -> a) -> CircularVector a -> a
foldr1 :: (a -> a -> a) -> CircularVector a -> a
foldr1 = (a -> a -> a) -> CircularVector a -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
Foldable.foldr1

-- | @since 0.1
foldl1 :: (a -> a -> a) -> CircularVector a -> a
foldl1 :: (a -> a -> a) -> CircularVector a -> a
foldl1 = (a -> a -> a) -> CircularVector a -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
Foldable.foldl1

-- | @since 0.1
toNonEmpty :: CircularVector a -> NonEmpty a
toNonEmpty :: CircularVector a -> NonEmpty a
toNonEmpty = CircularVector a -> NonEmpty a
forall (t :: * -> *) a. Foldable1 t => t a -> NonEmpty a
Foldable1.toNonEmpty

-- | Lazily-accumulating semigroupoidal fold over
--   a 'CircularVector'.
--
--   @since 0.1
foldMap1 :: Semigroup m => (a -> m) -> CircularVector a -> m
foldMap1 :: (a -> m) -> CircularVector a -> m
foldMap1 a -> m
f = \CircularVector a
v ->
  let len :: Int
len = CircularVector a -> Int
forall a. CircularVector a -> Int
Data.Vector.Circular.length CircularVector a
v
      go :: Int -> m
go !Int
ix
        | Int
ix Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
lenInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 = a -> m
f (CircularVector a -> Int -> a
forall a. CircularVector a -> Int -> a
index CircularVector a
v Int
ix) m -> m -> m
forall a. Semigroup a => a -> a -> a
<> Int -> m
go (Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
        | Bool
otherwise  = a -> m
f (CircularVector a -> a
forall a. CircularVector a -> a
last CircularVector a
v)
  in Int -> m
go Int
0
{-# inline foldMap1 #-}

-- | Strictly-accumulating semigroupoidal fold over
--   a 'CircularVector'.
--
--   @since 0.1
foldMap1' :: Semigroup m => (a -> m) -> CircularVector a -> m
foldMap1' :: (a -> m) -> CircularVector a -> m
foldMap1' a -> m
f = \CircularVector a
v ->
  let len :: Int
len = CircularVector a -> Int
forall a. CircularVector a -> Int
Data.Vector.Circular.length CircularVector a
v
      go :: Int -> m -> m
go !Int
ix !m
acc
        | Int
ix Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len = Int -> m -> m
go (Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) (m
acc m -> m -> m
forall a. Semigroup a => a -> a -> a
<> a -> m
f (CircularVector a -> Int -> a
forall a. CircularVector a -> Int -> a
index CircularVector a
v Int
ix))
        | Bool
otherwise = m
acc
  in Int -> m -> m
go Int
1 (a -> m
f (CircularVector a -> a
forall a. CircularVector a -> a
head CircularVector a
v))
{-# inline foldMap1' #-}

-- | Construct a 'Vector' from a 'CircularVector'.
--
--   @since 0.1
toVector :: CircularVector a -> Vector a
toVector :: CircularVector a -> Vector a
toVector CircularVector a
v = Int -> (Int -> a) -> Vector a
forall a. Int -> (Int -> a) -> Vector a
Vector.generate (CircularVector a -> Int
forall a. CircularVector a -> Int
length CircularVector a
v) (CircularVector a -> Int -> a
forall a. CircularVector a -> Int -> a
index CircularVector a
v)

-- | Construct a 'NonEmptyVector' from a 'CircularVector'.
--
--   @since 0.1.1
toNonEmptyVector :: CircularVector a -> NonEmptyVector a
toNonEmptyVector :: CircularVector a -> NonEmptyVector a
toNonEmptyVector CircularVector a
v = Int -> (Int -> a) -> NonEmptyVector a
forall a. Int -> (Int -> a) -> NonEmptyVector a
NonEmpty.generate1 (CircularVector a -> Int
forall a. CircularVector a -> Int
length CircularVector a
v) (CircularVector a -> Int -> a
forall a. CircularVector a -> Int -> a
index CircularVector a
v)

-- | Construct a 'CircularVector' from a 'NonEmptyVector'.
--
--   @since 0.1
fromVector :: NonEmptyVector a -> CircularVector a
fromVector :: NonEmptyVector a -> CircularVector a
fromVector NonEmptyVector a
v = NonEmptyVector a -> Int -> CircularVector a
forall a. NonEmptyVector a -> Int -> CircularVector a
CircularVector NonEmptyVector a
v Int
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 :: Vector a -> CircularVector a
unsafeFromVector = NonEmptyVector a -> CircularVector a
forall a. NonEmptyVector a -> CircularVector a
fromVector (NonEmptyVector a -> CircularVector a)
-> (Vector a -> NonEmptyVector a) -> Vector a -> CircularVector a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector a -> NonEmptyVector a
forall a. Vector a -> NonEmptyVector a
NonEmpty.unsafeFromVector

-- | Construct a 'CircularVector' from a list.
--
--   @since 0.1
fromList :: [a] -> Maybe (CircularVector a)
fromList :: [a] -> Maybe (CircularVector a)
fromList [a]
xs = Int -> [a] -> Maybe (CircularVector a)
forall a. Int -> [a] -> Maybe (CircularVector a)
fromListN ([a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length [a]
xs) [a]
xs
{-# inline fromList #-}

-- | Construct a 'CircularVector' from a list with a size hint.
--
--   @since 0.1
fromListN :: Int -> [a] -> Maybe (CircularVector a)
fromListN :: Int -> [a] -> Maybe (CircularVector a)
fromListN Int
n [a]
xs = NonEmptyVector a -> CircularVector a
forall a. NonEmptyVector a -> CircularVector a
fromVector (NonEmptyVector a -> CircularVector a)
-> Maybe (NonEmptyVector a) -> Maybe (CircularVector a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int -> [a] -> Maybe (NonEmptyVector a)
forall a. Int -> [a] -> Maybe (NonEmptyVector a)
NonEmpty.fromListN Int
n [a]
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 :: [a] -> CircularVector a
unsafeFromList [a]
xs = Int -> [a] -> CircularVector a
forall a. Int -> [a] -> CircularVector a
unsafeFromListN ([a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length [a]
xs) [a]
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 :: Int -> [a] -> CircularVector a
unsafeFromListN Int
n [a]
xs
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = String -> CircularVector a
forall a. HasCallStack => String -> a
error String
"Data.Vector.Circular.unsafeFromListN: invalid length!"
  | Bool
otherwise = Vector a -> CircularVector a
forall a. Vector a -> CircularVector a
unsafeFromVector (Int -> [a] -> Vector a
forall a. Int -> [a] -> Vector a
Vector.fromListN Int
n [a]
xs)

-- | Construct a singleton 'CircularVector.
--
--   @since 0.1
singleton :: a -> CircularVector a
singleton :: a -> CircularVector a
singleton = NonEmptyVector a -> CircularVector a
forall a. NonEmptyVector a -> CircularVector a
fromVector (NonEmptyVector a -> CircularVector a)
-> (a -> NonEmptyVector a) -> a -> CircularVector a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> NonEmptyVector a
forall a. a -> NonEmptyVector a
NonEmpty.singleton
{-# inline singleton #-}

-- | Index into a 'CircularVector'. This is always total.
--
--   @since 0.1
index :: CircularVector a -> Int -> a
index :: CircularVector a -> Int -> a
index (CircularVector NonEmptyVector a
v Int
r) = \ !Int
ix ->
  let len :: Int
len = NonEmptyVector a -> Int
forall a. NonEmptyVector a -> Int
NonEmpty.length NonEmptyVector a
v
  in NonEmptyVector a -> Int -> a
forall a. NonEmptyVector a -> Int -> a
NonEmpty.unsafeIndex NonEmptyVector a
v (Int -> Int -> Int
unsafeMod (Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
r) Int
len)
{-# inline index #-}

-- | Get the first element of a 'CircularVector'. This is always total.
--
--   @since 0.1
head :: CircularVector a -> a
head :: CircularVector a -> a
head CircularVector a
v = CircularVector a -> Int -> a
forall a. CircularVector a -> Int -> a
index CircularVector a
v Int
0
{-# inline head #-}

-- | Get the last element of a 'CircularVector'. This is always total.
--
--   @since 0.1
last :: CircularVector a -> a
last :: CircularVector a -> a
last CircularVector a
v = CircularVector a -> Int -> a
forall a. CircularVector a -> Int -> a
index CircularVector a
v (CircularVector a -> Int
forall a. CircularVector a -> Int
Data.Vector.Circular.length CircularVector a
v Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
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 :: Int -> CircularVector a -> CircularVector a
rotateRight Int
r' (CircularVector NonEmptyVector a
v Int
r) = NonEmptyVector a -> Int -> CircularVector a
forall a. NonEmptyVector a -> Int -> CircularVector a
CircularVector NonEmptyVector a
v Int
h
  where
    len :: Int
len = NonEmptyVector a -> Int
forall a. NonEmptyVector a -> Int
NonEmpty.length NonEmptyVector a
v
    h :: Int
h = Int -> Int -> Int
unsafeMod (Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int -> Int
unsafeMod Int
r' Int
len) Int
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 :: Int -> CircularVector a -> CircularVector a
rotateLeft Int
r' (CircularVector NonEmptyVector a
v Int
r) = NonEmptyVector a -> Int -> CircularVector a
forall a. NonEmptyVector a -> Int -> CircularVector a
CircularVector NonEmptyVector a
v Int
h
  where
    len :: Int
len = NonEmptyVector a -> Int
forall a. NonEmptyVector a -> Int
NonEmpty.length NonEmptyVector a
v
    h :: Int
h = Int -> Int -> Int
unsafeMod (Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int -> Int -> Int
unsafeMod Int
r' Int
len) Int
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 :: [a] -> Q (TExp (CircularVector a))
vec [] = String -> Q (TExp (CircularVector a))
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Cannot create an empty CircularVector!"
vec [a]
xs =
#if MIN_VERSION_template_haskell(2,16,0)
  CircularVector a -> Q (TExp (CircularVector a))
forall t. Lift t => t -> Q (TExp t)
liftTyped ([a] -> CircularVector a
forall a. [a] -> CircularVector a
unsafeFromList [a]
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 :: CircularVector a -> CircularVector a -> Bool
equivalent CircularVector a
x CircularVector a
y = CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
vector (CircularVector a -> CircularVector a
forall a. Ord a => CircularVector a -> CircularVector a
canonise CircularVector a
x) NonEmptyVector a -> NonEmptyVector a -> Bool
forall a. Eq a => a -> a -> Bool
== CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
vector (CircularVector a -> CircularVector a
forall a. Ord a => CircularVector a -> CircularVector a
canonise CircularVector a
y)

-- | @since 0.1
canonise :: Ord a => CircularVector a -> CircularVector a
canonise :: CircularVector a -> CircularVector a
canonise (CircularVector NonEmptyVector a
v Int
r) = NonEmptyVector a -> Int -> CircularVector a
forall a. NonEmptyVector a -> Int -> CircularVector a
CircularVector NonEmptyVector a
v' (Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
lr)
  where
    lr :: Int
lr = Vector a -> Int
forall a. Ord a => Vector a -> Int
leastRotation (NonEmptyVector a -> Vector a
forall a. NonEmptyVector a -> Vector a
NonEmpty.toVector NonEmptyVector a
v)
    v' :: NonEmptyVector a
v' = CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
toNonEmptyVector (Int -> CircularVector a -> CircularVector a
forall a. Int -> CircularVector a -> CircularVector a
rotateRight Int
lr (NonEmptyVector a -> Int -> CircularVector a
forall a. NonEmptyVector a -> Int -> CircularVector a
CircularVector NonEmptyVector a
v Int
0))

-- | @since 0.1
leastRotation :: forall a. (Ord a) => Vector a -> Int
leastRotation :: Vector a -> Int
leastRotation Vector a
v = (forall s. ST s Int) -> Int
forall a. (forall s. ST s a) -> a
runST forall s. ST s Int
go
  where
    go :: forall s. ST s Int
    go :: ST s Int
go = do
      let s :: Vector a
s = Vector a
v Vector a -> Vector a -> Vector a
forall a. Semigroup a => a -> a -> a
<> Vector a
v
      let len :: Int
len = Vector a -> Int
forall a. Vector a -> Int
Vector.length Vector a
s
      MVector s Int
f <- Int -> Int -> ST s (MVector (PrimState (ST s)) Int)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> a -> m (MVector (PrimState m) a)
MVector.replicate @_ @Int Int
len (-Int
1)
      MutVar s Int
kVar <- Int -> ST s (MutVar (PrimState (ST s)) Int)
forall (m :: * -> *) a.
PrimMonad m =>
a -> m (MutVar (PrimState m) a)
newMutVar @_ @Int Int
0
      [Int] -> (Int -> ST s ()) -> ST s ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Int
1..Int
lenInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1] ((Int -> ST s ()) -> ST s ()) -> (Int -> ST s ()) -> ST s ()
forall a b. (a -> b) -> a -> b
$ \Int
j -> do
        a
sj <- Vector a -> Int -> ST s a
forall (m :: * -> *) a. Monad m => Vector a -> Int -> m a
Vector.indexM Vector a
s Int
j
        Int
i0 <- MutVar (PrimState (ST s)) Int -> ST s Int
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar MutVar s Int
MutVar (PrimState (ST s)) Int
kVar ST s Int -> (Int -> ST s Int) -> ST s Int
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Int
k -> MVector (PrimState (ST s)) Int -> Int -> ST s Int
forall (m :: * -> *) a.
PrimMonad m =>
MVector (PrimState m) a -> Int -> m a
MVector.read MVector s Int
MVector (PrimState (ST s)) Int
f (Int
j Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
        let loop :: Int -> ST s Int
loop Int
i = do
              a
a <- MutVar (PrimState (ST s)) Int -> ST s Int
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar MutVar s Int
MutVar (PrimState (ST s)) Int
kVar ST s Int -> (Int -> ST s a) -> ST s a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Int
k -> Vector a -> Int -> ST s a
forall (m :: * -> *) a. Monad m => Vector a -> Int -> m a
Vector.indexM Vector a
s (Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
              if (Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= (-Int
1) Bool -> Bool -> Bool
&& a
sj a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
a)
                then do
                  Bool -> ST s () -> ST s ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (a
sj a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
a) (MutVar (PrimState (ST s)) Int -> Int -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> a -> m ()
writeMutVar MutVar s Int
MutVar (PrimState (ST s)) Int
kVar (Int
j Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1))
                  Int -> ST s Int
loop (Int -> ST s Int) -> ST s Int -> ST s Int
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< MVector (PrimState (ST s)) Int -> Int -> ST s Int
forall (m :: * -> *) a.
PrimMonad m =>
MVector (PrimState m) a -> Int -> m a
MVector.read MVector s Int
MVector (PrimState (ST s)) Int
f Int
i
                else Int -> ST s Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
i
        Int
i <- Int -> ST s Int
loop Int
i0
        a
a <- MutVar (PrimState (ST s)) Int -> ST s Int
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar MutVar s Int
MutVar (PrimState (ST s)) Int
kVar ST s Int -> (Int -> ST s a) -> ST s a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Int
k -> Vector a -> Int -> ST s a
forall (m :: * -> *) a. Monad m => Vector a -> Int -> m a
Vector.indexM Vector a
s (Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
        if a
sj a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
a
          then do
            MutVar (PrimState (ST s)) Int -> ST s Int
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar MutVar s Int
MutVar (PrimState (ST s)) Int
kVar ST s Int -> (Int -> ST s ()) -> ST s ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Int
k -> Bool -> ST s () -> ST s ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (a
sj a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< (Vector a
s Vector a -> Int -> a
forall a. Vector a -> Int -> a
Vector.! Int
k)) (MutVar (PrimState (ST s)) Int -> Int -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> a -> m ()
writeMutVar MutVar s Int
MutVar (PrimState (ST s)) Int
kVar Int
j)
            MutVar (PrimState (ST s)) Int -> ST s Int
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar MutVar s Int
MutVar (PrimState (ST s)) Int
kVar ST s Int -> (Int -> ST s ()) -> ST s ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Int
k -> MVector (PrimState (ST s)) Int -> Int -> Int -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
MVector (PrimState m) a -> Int -> a -> m ()
MVector.write MVector s Int
MVector (PrimState (ST s)) Int
f (Int
j Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k) (-Int
1)
          else do
            MutVar (PrimState (ST s)) Int -> ST s Int
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar MutVar s Int
MutVar (PrimState (ST s)) Int
kVar ST s Int -> (Int -> ST s ()) -> ST s ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Int
k -> MVector (PrimState (ST s)) Int -> Int -> Int -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
MVector (PrimState m) a -> Int -> a -> m ()
MVector.write MVector s Int
MVector (PrimState (ST s)) Int
f (Int
j Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k) (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
      MutVar (PrimState (ST s)) Int -> ST s Int
forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar MutVar s Int
MutVar (PrimState (ST s)) Int
kVar

-- only safe if second argument is nonzero.
-- used internally for modulus operations with length.
unsafeMod :: Int -> Int -> Int
unsafeMod :: Int -> Int -> Int
unsafeMod = Int -> Int -> Int
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 :: (a -> b -> c)
-> CircularVector a -> CircularVector b -> CircularVector c
zipWith a -> b -> c
f CircularVector a
a CircularVector b
b = NonEmptyVector c -> CircularVector c
forall a. NonEmptyVector a -> CircularVector a
fromVector (NonEmptyVector c -> CircularVector c)
-> NonEmptyVector c -> CircularVector c
forall a b. (a -> b) -> a -> b
$ (a -> b -> c)
-> NonEmptyVector a -> NonEmptyVector b -> NonEmptyVector c
forall a b c.
(a -> b -> c)
-> NonEmptyVector a -> NonEmptyVector b -> NonEmptyVector c
NonEmpty.zipWith a -> b -> c
f (CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
toNonEmptyVector CircularVector a
a) (CircularVector b -> NonEmptyVector b
forall a. CircularVector a -> NonEmptyVector a
toNonEmptyVector CircularVector b
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 :: (a -> b -> c -> d)
-> CircularVector a
-> CircularVector b
-> CircularVector c
-> CircularVector d
zipWith3 a -> b -> c -> d
f CircularVector a
a CircularVector b
b CircularVector c
c = NonEmptyVector d -> CircularVector d
forall a. NonEmptyVector a -> CircularVector a
fromVector (NonEmptyVector d -> CircularVector d)
-> NonEmptyVector d -> CircularVector d
forall a b. (a -> b) -> a -> b
$
  (a -> b -> c -> d)
-> NonEmptyVector a
-> NonEmptyVector b
-> NonEmptyVector c
-> NonEmptyVector d
forall a b c d.
(a -> b -> c -> d)
-> NonEmptyVector a
-> NonEmptyVector b
-> NonEmptyVector c
-> NonEmptyVector d
NonEmpty.zipWith3 a -> b -> c -> d
f (CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
toNonEmptyVector CircularVector a
a) (CircularVector b -> NonEmptyVector b
forall a. CircularVector a -> NonEmptyVector a
toNonEmptyVector CircularVector b
b) (CircularVector c -> NonEmptyVector c
forall a. CircularVector a -> NonEmptyVector a
toNonEmptyVector CircularVector c
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 :: CircularVector a -> CircularVector b -> CircularVector (a, b)
zip CircularVector a
a CircularVector b
b = NonEmptyVector (a, b) -> CircularVector (a, b)
forall a. NonEmptyVector a -> CircularVector a
fromVector (NonEmptyVector (a, b) -> CircularVector (a, b))
-> NonEmptyVector (a, b) -> CircularVector (a, b)
forall a b. (a -> b) -> a -> b
$ NonEmptyVector a -> NonEmptyVector b -> NonEmptyVector (a, b)
forall a b.
NonEmptyVector a -> NonEmptyVector b -> NonEmptyVector (a, b)
NonEmpty.zip (CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
toNonEmptyVector CircularVector a
a) (CircularVector b -> NonEmptyVector b
forall a. CircularVector a -> NonEmptyVector a
toNonEmptyVector CircularVector b
b)

-- | Zip together three circular vectors.
--
--   @since 0.1.1
zip3 :: CircularVector a -> CircularVector b -> CircularVector c -> CircularVector (a,b,c)
zip3 :: CircularVector a
-> CircularVector b -> CircularVector c -> CircularVector (a, b, c)
zip3 CircularVector a
a CircularVector b
b CircularVector c
c = NonEmptyVector (a, b, c) -> CircularVector (a, b, c)
forall a. NonEmptyVector a -> CircularVector a
fromVector (NonEmptyVector (a, b, c) -> CircularVector (a, b, c))
-> NonEmptyVector (a, b, c) -> CircularVector (a, b, c)
forall a b. (a -> b) -> a -> b
$ NonEmptyVector a
-> NonEmptyVector b -> NonEmptyVector c -> NonEmptyVector (a, b, c)
forall a b c.
NonEmptyVector a
-> NonEmptyVector b -> NonEmptyVector c -> NonEmptyVector (a, b, c)
NonEmpty.zip3 (CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
toNonEmptyVector CircularVector a
a) (CircularVector b -> NonEmptyVector b
forall a. CircularVector a -> NonEmptyVector a
toNonEmptyVector CircularVector b
b) (CircularVector c -> NonEmptyVector c
forall a. CircularVector a -> NonEmptyVector a
toNonEmptyVector CircularVector c
c)

-- | /O(n)/ Reverse a circular vector.
--
--   @since 0.1.1
reverse :: CircularVector a -> CircularVector a
reverse :: CircularVector a -> CircularVector a
reverse = NonEmptyVector a -> CircularVector a
forall a. NonEmptyVector a -> CircularVector a
fromVector (NonEmptyVector a -> CircularVector a)
-> (CircularVector a -> NonEmptyVector a)
-> CircularVector a
-> CircularVector a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmptyVector a -> NonEmptyVector a
forall a. NonEmptyVector a -> NonEmptyVector a
NonEmpty.reverse (NonEmptyVector a -> NonEmptyVector a)
-> (CircularVector a -> NonEmptyVector a)
-> CircularVector a
-> NonEmptyVector a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
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 :: (a -> a -> Ordering) -> CircularVector a -> CircularVector a
rotateToMinimumBy a -> a -> Ordering
f (CircularVector NonEmptyVector a
v Int
_rot) =
  NonEmptyVector a -> Int -> CircularVector a
forall a. NonEmptyVector a -> Int -> CircularVector a
CircularVector NonEmptyVector a
v ((a -> a -> Ordering) -> NonEmptyVector a -> Int
forall a. (a -> a -> Ordering) -> NonEmptyVector a -> Int
NonEmpty.minIndexBy a -> a -> Ordering
f NonEmptyVector a
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 :: (a -> a -> Ordering) -> CircularVector a -> CircularVector a
rotateToMaximumBy a -> a -> Ordering
f (CircularVector NonEmptyVector a
v Int
_rot) =
  NonEmptyVector a -> Int -> CircularVector a
forall a. NonEmptyVector a -> Int -> CircularVector a
CircularVector NonEmptyVector a
v ((a -> a -> Ordering) -> NonEmptyVector a -> Int
forall a. (a -> a -> Ordering) -> NonEmptyVector a -> Int
NonEmpty.maxIndexBy a -> a -> Ordering
f NonEmptyVector a
v)

-- | /O(n)/ Check if all elements satisfy the predicate.
--
--   @since 0.1.1
all :: (a -> Bool) -> CircularVector a -> Bool
all :: (a -> Bool) -> CircularVector a -> Bool
all a -> Bool
f = (a -> Bool) -> NonEmptyVector a -> Bool
forall a. (a -> Bool) -> NonEmptyVector a -> Bool
NonEmpty.all a -> Bool
f (NonEmptyVector a -> Bool)
-> (CircularVector a -> NonEmptyVector a)
-> CircularVector a
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
vector

-- | /O(n)/ Check if any element satisfies the predicate.
--
--   @since 0.1.1
any :: (a -> Bool) -> CircularVector a -> Bool
any :: (a -> Bool) -> CircularVector a -> Bool
any a -> Bool
f = (a -> Bool) -> NonEmptyVector a -> Bool
forall a. (a -> Bool) -> NonEmptyVector a -> Bool
NonEmpty.any a -> Bool
f (NonEmptyVector a -> Bool)
-> (CircularVector a -> NonEmptyVector a)
-> CircularVector a
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
vector

-- | /O(n)/ Check if all elements are True.
--
--   @since 0.1.1
and :: CircularVector Bool -> Bool
and :: CircularVector Bool -> Bool
and = NonEmptyVector Bool -> Bool
NonEmpty.and (NonEmptyVector Bool -> Bool)
-> (CircularVector Bool -> NonEmptyVector Bool)
-> CircularVector Bool
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CircularVector Bool -> NonEmptyVector Bool
forall a. CircularVector a -> NonEmptyVector a
vector

-- | /O(n)/ Check if any element is True.
--
--   @since 0.1.1
or :: CircularVector Bool -> Bool
or :: CircularVector Bool -> Bool
or = NonEmptyVector Bool -> Bool
NonEmpty.or (NonEmptyVector Bool -> Bool)
-> (CircularVector Bool -> NonEmptyVector Bool)
-> CircularVector Bool
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CircularVector Bool -> NonEmptyVector Bool
forall a. CircularVector a -> NonEmptyVector a
vector

-- | /O(n)/ Compute the sum of the elements.
--
--   @since 0.1.1
sum :: Num a => CircularVector a -> a
sum :: CircularVector a -> a
sum = NonEmptyVector a -> a
forall a. Num a => NonEmptyVector a -> a
NonEmpty.sum (NonEmptyVector a -> a)
-> (CircularVector a -> NonEmptyVector a) -> CircularVector a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
vector

-- | /O(n)/ Compute the product of the elements.
--
--   @since 0.1.1
product :: Num a => CircularVector a -> a
product :: CircularVector a -> a
product = NonEmptyVector a -> a
forall a. Num a => NonEmptyVector a -> a
NonEmpty.sum (NonEmptyVector a -> a)
-> (CircularVector a -> NonEmptyVector a) -> CircularVector a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
vector

-- | /O(n)/ Yield the maximum element of the circular vector.
--
--   @since 0.1.1
maximum :: Ord a => CircularVector a -> a
maximum :: CircularVector a -> a
maximum = NonEmptyVector a -> a
forall a. Ord a => NonEmptyVector a -> a
NonEmpty.maximum (NonEmptyVector a -> a)
-> (CircularVector a -> NonEmptyVector a) -> CircularVector a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
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 :: (a -> a -> Ordering) -> CircularVector a -> a
maximumBy a -> a -> Ordering
f = (a -> a -> Ordering) -> NonEmptyVector a -> a
forall a. (a -> a -> Ordering) -> NonEmptyVector a -> a
NonEmpty.maximumBy a -> a -> Ordering
f (NonEmptyVector a -> a)
-> (CircularVector a -> NonEmptyVector a) -> CircularVector a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
vector

-- | /O(n)/ Yield the minimum element of the circular vector.
--
--   @since 0.1.1
minimum :: Ord a => CircularVector a -> a
minimum :: CircularVector a -> a
minimum = NonEmptyVector a -> a
forall a. Ord a => NonEmptyVector a -> a
NonEmpty.minimum (NonEmptyVector a -> a)
-> (CircularVector a -> NonEmptyVector a) -> CircularVector a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
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 :: (a -> a -> Ordering) -> CircularVector a -> a
minimumBy a -> a -> Ordering
f = (a -> a -> Ordering) -> NonEmptyVector a -> a
forall a. (a -> a -> Ordering) -> NonEmptyVector a -> a
NonEmpty.minimumBy a -> a -> Ordering
f (NonEmptyVector a -> a)
-> (CircularVector a -> NonEmptyVector a) -> CircularVector a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CircularVector a -> NonEmptyVector a
forall a. CircularVector a -> NonEmptyVector a
vector