{-# LANGUAGE FlexibleContexts #-}
-- |
-- Module      : Data.Massiv.Vector.Unsafe
-- Copyright   : (c) Alexey Kuleshevich 2020-2022
-- License     : BSD3
-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
-- Stability   : experimental
-- Portability : non-portable
--
module Data.Massiv.Vector.Unsafe
  (
  -- * Vector
  -- ** Accessors
  -- *** Indexing
    unsafeHead
  , unsafeLast
  -- *** Monadic Indexing
  , unsafeIndexM
  , unsafeHeadM
  , unsafeLastM
  -- *** Slicing
  , unsafeInit
  , unsafeTail
  , unsafeTake
  , unsafeDrop
  -- -- ** Modifying
  -- -- *** Bulk updates
  -- , unsafeUpdate
  -- , unsafeUpdate_
  -- -- *** Accumulation
  -- , unsafeAccum
  -- , unsafeAccumulate_
  -- , unsafeBackpermute
  -- -- ** Predicates
  -- , unsafePartition
  -- ** Unbounded streams
  , unsafeUnfoldrN
  , unsafeUnfoldrNM
  , unsafeFromListN
  ) where

import Data.Coerce
import Data.Massiv.Core.Common
import Data.Massiv.Array.Delayed.Stream
import qualified Data.Massiv.Vector.Stream as S

-- ========= --
-- Accessors --
-- ========= --

--------------
-- Indexing --
--------------


-- |
--
-- @since 0.5.0
unsafeHead :: Source r e => Vector r e -> e
unsafeHead :: Vector r e -> e
unsafeHead = (Vector r e -> Int -> e
forall r e ix. (Source r e, Index ix) => Array r ix e -> Int -> e
`unsafeLinearIndex` Int
0)
{-# INLINE unsafeHead #-}

-- |
--
-- @since 0.5.0
unsafeLast :: Source r e => Vector r e -> e
unsafeLast :: Vector r e -> e
unsafeLast Vector r e
v = Vector r e -> Int -> e
forall r e ix. (Source r e, Index ix) => Array r ix e -> Int -> e
unsafeLinearIndex Vector r e
v (Sz Int -> Int
forall ix. Sz ix -> ix
unSz (Vector r e -> Sz Int
forall r ix e. Size r => Array r ix e -> Sz ix
size Vector r e
v) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
{-# INLINE unsafeLast #-}

----------------------
-- Monadic indexing --
----------------------

-- |
--
-- @since 0.5.0
unsafeIndexM :: (Source r e, Monad m) => Vector r e -> Ix1 -> m e
unsafeIndexM :: Vector r e -> Int -> m e
unsafeIndexM Vector r e
v Int
i = e -> m e
forall (f :: * -> *) a. Applicative f => a -> f a
pure (e -> m e) -> e -> m e
forall a b. (a -> b) -> a -> b
$! Vector r e -> Int -> e
forall r e ix. (Source r e, Index ix) => Array r ix e -> Int -> e
unsafeLinearIndex Vector r e
v Int
i
{-# INLINE unsafeIndexM #-}


-- |
--
-- @since 0.5.0
unsafeHeadM :: (Monad m, Source r e) => Vector r e -> m e
unsafeHeadM :: Vector r e -> m e
unsafeHeadM Vector r e
v = e -> m e
forall (f :: * -> *) a. Applicative f => a -> f a
pure (e -> m e) -> e -> m e
forall a b. (a -> b) -> a -> b
$! Vector r e -> e
forall r e. Source r e => Vector r e -> e
unsafeHead Vector r e
v
{-# INLINE unsafeHeadM #-}

-- |
--
-- @since 0.5.0
unsafeLastM :: (Monad m, Source r e) => Vector r e -> m e
unsafeLastM :: Vector r e -> m e
unsafeLastM Vector r e
v = e -> m e
forall (f :: * -> *) a. Applicative f => a -> f a
pure (e -> m e) -> e -> m e
forall a b. (a -> b) -> a -> b
$! Vector r e -> e
forall r e. Source r e => Vector r e -> e
unsafeLast Vector r e
v
{-# INLINE unsafeLastM #-}


-------------
-- Slicing --
-------------


-- |
--
-- @since 0.5.0
unsafeInit :: Source r e => Vector r e -> Vector r e
unsafeInit :: Vector r e -> Vector r e
unsafeInit Vector r e
v = Int -> Sz Int -> Vector r e -> Vector r e
forall r e ix.
(Source r e, Index ix) =>
Int -> Sz Int -> Array r ix e -> Array r Int e
unsafeLinearSlice Int
0 (Int -> Sz Int
forall ix. ix -> Sz ix
SafeSz (Sz Int -> Int
coerce (Vector r e -> Sz Int
forall r ix e. Size r => Array r ix e -> Sz ix
size Vector r e
v) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)) Vector r e
v
{-# INLINE unsafeInit #-}


-- |
--
-- @since 0.5.0
unsafeTail :: Source r e => Vector r e -> Vector r e
unsafeTail :: Vector r e -> Vector r e
unsafeTail = Sz Int -> Vector r e -> Vector r e
forall r e. Source r e => Sz Int -> Vector r e -> Vector r e
unsafeDrop Sz Int
forall ix. Index ix => Sz ix
oneSz
{-# INLINE unsafeTail #-}


-- |
--
-- @since 0.5.0
unsafeTake :: Source r e => Sz1 -> Vector r e -> Vector r e
unsafeTake :: Sz Int -> Vector r e -> Vector r e
unsafeTake = Int -> Sz Int -> Vector r e -> Vector r e
forall r e ix.
(Source r e, Index ix) =>
Int -> Sz Int -> Array r ix e -> Array r Int e
unsafeLinearSlice Int
0
{-# INLINE unsafeTake #-}

-- |
--
-- @since 0.5.0
unsafeDrop :: Source r e => Sz1 -> Vector r e -> Vector r e
unsafeDrop :: Sz Int -> Vector r e -> Vector r e
unsafeDrop (Sz Int
d) Vector r e
v = Int -> Sz Int -> Vector r e -> Vector r e
forall r e ix.
(Source r e, Index ix) =>
Int -> Sz Int -> Array r ix e -> Array r Int e
unsafeLinearSlice Int
d (Int -> Sz Int
forall ix. ix -> Sz ix
SafeSz (Sz Int -> Int
coerce (Vector r e -> Sz Int
forall r ix e. Size r => Array r ix e -> Sz ix
size Vector r e
v) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
d)) Vector r e
v
{-# INLINE unsafeDrop #-}


-- | /O(n)/ - Convert a list of a known length to a delayed stream vector.
--
-- /Unsafe/ - This function is unsafe because it will allocate enough space in memory for
-- @n@ elements ahead of time, regardless of the actual size of the list. Supplying @n@
-- that is too big will result in an asynchronous `Control.Exception.Base.HeapOverflow`
-- exception.
--
-- @since 0.5.1
unsafeFromListN :: Sz1 -> [e] -> Vector DS e
unsafeFromListN :: Sz Int -> [e] -> Vector DS e
unsafeFromListN Sz Int
n = Steps Id e -> Vector DS e
forall e. Steps Id e -> Vector DS e
fromSteps (Steps Id e -> Vector DS e)
-> ([e] -> Steps Id e) -> [e] -> Vector DS e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sz Int -> [e] -> Steps Id e
forall (m :: * -> *) e. Monad m => Sz Int -> [e] -> Steps m e
S.unsafeFromListN Sz Int
n
{-# INLINE unsafeFromListN #-}

-- | /O(n)/ - Right unfolding function with at most @n@ number of elements.
--
-- /Unsafe/ - This function is unsafe because it will allocate enough space in memory for
-- @n@ elements ahead of time, regardless of when unfolding function returns a
-- `Nothing`. Supplying @n@ that is too big will result in an asynchronous
-- `Control.Exception.Base.HeapOverflow` exception.
--
-- @since 0.5.1
unsafeUnfoldrN ::
     Sz1
  -- ^ @n@ - maximum number of elements that the vector will have
  -> (s -> Maybe (e, s))
  -- ^ Unfolding function. Stops when `Nothing` is returned or maximum number of elements
  -- is reached.
  -> s -- ^ Inititial element.
  -> Vector DS e
unsafeUnfoldrN :: Sz Int -> (s -> Maybe (e, s)) -> s -> Vector DS e
unsafeUnfoldrN Sz Int
n s -> Maybe (e, s)
f = Steps Id e -> Vector DS e
forall e. Steps Id e -> Vector DS e
DSArray (Steps Id e -> Vector DS e)
-> (s -> Steps Id e) -> s -> Vector DS e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sz Int -> (s -> Maybe (e, s)) -> s -> Steps Id e
forall (m :: * -> *) s e.
Monad m =>
Sz Int -> (s -> Maybe (e, s)) -> s -> Steps m e
S.unsafeUnfoldrN Sz Int
n s -> Maybe (e, s)
f
{-# INLINE unsafeUnfoldrN #-}



-- | /O(n)/ - Same as `unsafeUnfoldrN`, but with monadic generating function.
--
-- /Unsafe/ - This function is unsafe because it will allocate enough space in memory for
-- @n@ elements ahead of time, regardless of when unfolding function returns a
-- `Nothing`. Supplying @n@ that is too big will result in an asynchronous
-- `Control.Exception.Base.HeapOverflow` exception.
--
-- @since 0.5.1
unsafeUnfoldrNM :: Monad m => Sz1 -> (s -> m (Maybe (e, s))) -> s -> m (Vector DS e)
unsafeUnfoldrNM :: Sz Int -> (s -> m (Maybe (e, s))) -> s -> m (Vector DS e)
unsafeUnfoldrNM Sz Int
n s -> m (Maybe (e, s))
f = Steps m e -> m (Vector DS e)
forall (m :: * -> *) e. Monad m => Steps m e -> m (Vector DS e)
fromStepsM (Steps m e -> m (Vector DS e))
-> (s -> Steps m e) -> s -> m (Vector DS e)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sz Int -> (s -> m (Maybe (e, s))) -> s -> Steps m e
forall (m :: * -> *) s e.
Monad m =>
Sz Int -> (s -> m (Maybe (e, s))) -> s -> Steps m e
S.unsafeUnfoldrNM Sz Int
n s -> m (Maybe (e, s))
f
{-# INLINE unsafeUnfoldrNM #-}