{-# 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.Array.Delayed.Stream
import Data.Massiv.Core.Common
import qualified Data.Massiv.Vector.Stream as S

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

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

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

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

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

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

-- |
--
-- @since 0.5.0
unsafeHeadM :: (Monad m, Source r e) => Vector r e -> m e
unsafeHeadM :: forall (m :: * -> *) r e.
(Monad m, Source r e) =>
Vector r e -> m e
unsafeHeadM Vector r e
v = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$! 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 :: forall (m :: * -> *) r e.
(Monad m, Source r e) =>
Vector r e -> m e
unsafeLastM Vector r e
v = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$! 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 :: forall r e. Source r e => Vector r e -> Vector r e
unsafeInit Vector r e
v = forall r e ix.
(Source r e, Index ix) =>
Ix1 -> Sz Ix1 -> Array r ix e -> Array r Ix1 e
unsafeLinearSlice Ix1
0 (forall ix. ix -> Sz ix
SafeSz (coerce :: forall a b. Coercible a b => a -> b
coerce (forall r ix e. Size r => Array r ix e -> Sz ix
size Vector r e
v) forall a. Num a => a -> a -> a
- Ix1
1)) Vector r e
v
{-# INLINE unsafeInit #-}

-- |
--
-- @since 0.5.0
unsafeTail :: Source r e => Vector r e -> Vector r e
unsafeTail :: forall r e. Source r e => Vector r e -> Vector r e
unsafeTail = forall r e. Source r e => Sz Ix1 -> Vector r e -> Vector r e
unsafeDrop 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 :: forall r e. Source r e => Sz Ix1 -> Vector r e -> Vector r e
unsafeTake = forall r e ix.
(Source r e, Index ix) =>
Ix1 -> Sz Ix1 -> Array r ix e -> Array r Ix1 e
unsafeLinearSlice Ix1
0
{-# INLINE unsafeTake #-}

-- |
--
-- @since 0.5.0
unsafeDrop :: Source r e => Sz1 -> Vector r e -> Vector r e
unsafeDrop :: forall r e. Source r e => Sz Ix1 -> Vector r e -> Vector r e
unsafeDrop (Sz Ix1
d) Vector r e
v = forall r e ix.
(Source r e, Index ix) =>
Ix1 -> Sz Ix1 -> Array r ix e -> Array r Ix1 e
unsafeLinearSlice Ix1
d (forall ix. ix -> Sz ix
SafeSz (coerce :: forall a b. Coercible a b => a -> b
coerce (forall r ix e. Size r => Array r ix e -> Sz ix
size Vector r e
v) forall a. Num a => a -> a -> a
- Ix1
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 :: forall e. Sz Ix1 -> [e] -> Vector DS e
unsafeFromListN Sz Ix1
n = forall e. Steps Id e -> Vector DS e
fromSteps forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) e. Monad m => Sz Ix1 -> [e] -> Steps m e
S.unsafeFromListN Sz Ix1
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 :: forall s e. Sz Ix1 -> (s -> Maybe (e, s)) -> s -> Vector DS e
unsafeUnfoldrN Sz Ix1
n s -> Maybe (e, s)
f = forall e. Steps Id e -> Vector DS e
DSArray forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) s e.
Monad m =>
Sz Ix1 -> (s -> Maybe (e, s)) -> s -> Steps m e
S.unsafeUnfoldrN Sz Ix1
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 :: forall (m :: * -> *) s e.
Monad m =>
Sz Ix1 -> (s -> m (Maybe (e, s))) -> s -> m (Vector DS e)
unsafeUnfoldrNM Sz Ix1
n s -> m (Maybe (e, s))
f = forall (m :: * -> *) e. Monad m => Steps m e -> m (Vector DS e)
fromStepsM forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) s e.
Monad m =>
Sz Ix1 -> (s -> m (Maybe (e, s))) -> s -> Steps m e
S.unsafeUnfoldrNM Sz Ix1
n s -> m (Maybe (e, s))
f
{-# INLINE unsafeUnfoldrNM #-}