{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}

-- |
-- Module      : Data.Massiv.Array.Unsafe
-- Copyright   : (c) Alexey Kuleshevich 2018-2022
-- License     : BSD3
-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
-- Stability   : experimental
-- Portability : non-portable
module Data.Massiv.Array.Unsafe (
  -- * Creation
  unsafeMakeLoadArray,
  unsafeMakeLoadArrayAdjusted,

  -- * Indexing
  Sz (SafeSz),
  Stride (SafeStride),
  unsafeIndex,
  unsafePrefIndex,
  unsafeLinearIndex,
  unsafeLinearIndexM,

  -- * Manipulations
  unsafeBackpermute,
  unsafeResize,
  unsafeExtract,
  unsafeTransform,
  unsafeTransform2,

  -- * Slicing
  unsafeSlice,
  unsafeOuterSlice,
  unsafeInnerSlice,
  unsafeLinearSlice,

  -- * Mutable interface
  unsafeResizeMArray,
  unsafeLinearSliceMArray,
  unsafeThaw,
  unsafeFreeze,
  unsafeNew,
  unsafeLoadIntoST,
  unsafeLoadIntoIO,
  unsafeLoadIntoS,
  unsafeLoadIntoM,
  unsafeCreateArray,
  unsafeCreateArray_,
  unsafeCreateArrayS,

  -- ** Read
  unsafeRead,
  unsafeLinearRead,

  -- ** Write
  unsafeWrite,
  unsafeLinearWrite,

  -- ** Modify
  unsafeModify,
  unsafeLinearModify,

  -- ** Swap
  unsafeSwap,
  unsafeLinearSwap,

  -- ** Range modification
  unsafeLinearSet,
  unsafeLinearCopy,
  unsafeArrayLinearCopy,

  -- ** Resizing
  unsafeLinearShrink,
  unsafeLinearGrow,

  -- * Pointer access
  unsafeMallocMArray,
  unsafeWithPtr,
  unsafeArrayToForeignPtr,
  unsafeMArrayToForeignPtr,
  unsafeArrayFromForeignPtr,
  unsafeArrayFromForeignPtr0,
  unsafeMArrayFromForeignPtr,
  unsafeMArrayFromForeignPtr0,

  -- ** Atomic Operations
  unsafeAtomicReadIntArray,
  unsafeAtomicWriteIntArray,
  unsafeAtomicModifyIntArray,
  unsafeAtomicAddIntArray,
  unsafeAtomicSubIntArray,
  unsafeAtomicAndIntArray,
  unsafeAtomicNandIntArray,
  unsafeAtomicOrIntArray,
  unsafeAtomicXorIntArray,
  unsafeCasIntArray,

  -- ** Other operations
  coerceBoxedArray,
  coerceNormalBoxedArray,
  unsafeUnstablePartitionRegionM,
  module Data.Massiv.Vector.Unsafe,
  module Data.Massiv.Array.Stencil.Unsafe,

  -- * Constructors
  Array (PArray, SArray, UArray, BArray, BLArray, BNArray, DArray, DLArray, DSArray, DIArray, DWArray),
  MArray (MPArray, MSArray, MUArray, MBArray, MBLArray, MBNArray),
) where

import Data.Massiv.Array.Delayed.Interleaved (Array (DIArray))
import Data.Massiv.Array.Delayed.Pull (
  D,
  unsafeExtract,
  unsafeInnerSlice,
  unsafeSlice,
 )
import Data.Massiv.Array.Delayed.Push (
  Array (DLArray),
  unsafeMakeLoadArray,
  unsafeMakeLoadArrayAdjusted,
 )
import Data.Massiv.Array.Delayed.Stream (Array (DSArray))
import Data.Massiv.Array.Delayed.Windowed (Array (DWArray))
import Data.Massiv.Array.Manifest.Boxed
import Data.Massiv.Array.Manifest.Internal
import Data.Massiv.Array.Manifest.Primitive
import Data.Massiv.Array.Manifest.Storable
import Data.Massiv.Array.Manifest.Unboxed
import Data.Massiv.Array.Mutable.Internal
import Data.Massiv.Array.Ops.Sort (unsafeUnstablePartitionRegionM)
import Data.Massiv.Array.Stencil.Unsafe
import Data.Massiv.Core.Common
import Data.Massiv.Core.Index.Stride (Stride (SafeStride))
import Data.Massiv.Vector.Unsafe

unsafeBackpermute
  :: (Index ix', Source r' e, Index ix)
  => Sz ix
  -> (ix -> ix')
  -> Array r' ix' e
  -> Array D ix e
unsafeBackpermute :: forall ix' r' e ix.
(Index ix', Source r' e, Index ix) =>
Sz ix -> (ix -> ix') -> Array r' ix' e -> Array D ix e
unsafeBackpermute !Sz ix
sz ix -> ix'
ixF !Array r' ix' e
arr = Comp -> Sz ix -> (ix -> e) -> Array D ix e
forall r ix e.
Load r ix e =>
Comp -> Sz ix -> (ix -> e) -> Array r ix e
makeArray (Array r' ix' e -> Comp
forall r ix e. Strategy r => Array r ix e -> Comp
forall ix e. Array r' ix e -> Comp
getComp Array r' ix' e
arr) Sz ix
sz (Array r' ix' e -> ix' -> e
forall ix. Index ix => Array r' ix e -> ix -> e
forall r e ix. (Source r e, Index ix) => Array r ix e -> ix -> e
unsafeIndex Array r' ix' e
arr (ix' -> e) -> (ix -> ix') -> ix -> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ix -> ix'
ixF)
{-# INLINE unsafeBackpermute #-}

-- | Same 'Data.Array.transform'', except no bounds checking is performed, thus making it faster,
-- but unsafe.
--
-- @since 0.3.0
unsafeTransform
  :: (Index ix', Source r' e', Index ix)
  => (Sz ix' -> (Sz ix, a))
  -> (a -> (ix' -> e') -> ix -> e)
  -> Array r' ix' e'
  -> Array D ix e
unsafeTransform :: forall ix' r' e' ix a e.
(Index ix', Source r' e', Index ix) =>
(Sz ix' -> (Sz ix, a))
-> (a -> (ix' -> e') -> ix -> e) -> Array r' ix' e' -> Array D ix e
unsafeTransform Sz ix' -> (Sz ix, a)
getSz a -> (ix' -> e') -> ix -> e
get Array r' ix' e'
arr = Comp -> Sz ix -> (ix -> e) -> Array D ix e
forall r ix e.
Load r ix e =>
Comp -> Sz ix -> (ix -> e) -> Array r ix e
makeArray (Array r' ix' e' -> Comp
forall r ix e. Strategy r => Array r ix e -> Comp
forall ix e. Array r' ix e -> Comp
getComp Array r' ix' e'
arr) Sz ix
sz (a -> (ix' -> e') -> ix -> e
get a
a (Array r' ix' e' -> ix' -> e'
forall ix. Index ix => Array r' ix e' -> ix -> e'
forall r e ix. (Source r e, Index ix) => Array r ix e -> ix -> e
unsafeIndex Array r' ix' e'
arr))
  where
    (Sz ix
sz, a
a) = Sz ix' -> (Sz ix, a)
getSz (Array r' ix' e' -> Sz ix'
forall r ix e. Size r => Array r ix e -> Sz ix
forall ix e. Array r' ix e -> Sz ix
size Array r' ix' e'
arr)
{-# INLINE unsafeTransform #-}

-- | Same 'Data.Array.transform2'', except no bounds checking is performed, thus making it faster,
-- but unsafe.
--
-- @since 0.3.0
unsafeTransform2
  :: (Index ix1, Source r1 e1, Index ix2, Source r2 e2, Index ix)
  => (Sz ix1 -> Sz ix2 -> (Sz ix, a))
  -> (a -> (ix1 -> e1) -> (ix2 -> e2) -> ix -> e)
  -> Array r1 ix1 e1
  -> Array r2 ix2 e2
  -> Array D ix e
unsafeTransform2 :: forall ix1 r1 e1 ix2 r2 e2 ix a e.
(Index ix1, Source r1 e1, Index ix2, Source r2 e2, Index ix) =>
(Sz ix1 -> Sz ix2 -> (Sz ix, a))
-> (a -> (ix1 -> e1) -> (ix2 -> e2) -> ix -> e)
-> Array r1 ix1 e1
-> Array r2 ix2 e2
-> Array D ix e
unsafeTransform2 Sz ix1 -> Sz ix2 -> (Sz ix, a)
getSz a -> (ix1 -> e1) -> (ix2 -> e2) -> ix -> e
get Array r1 ix1 e1
arr1 Array r2 ix2 e2
arr2 =
  Comp -> Sz ix -> (ix -> e) -> Array D ix e
forall r ix e.
Load r ix e =>
Comp -> Sz ix -> (ix -> e) -> Array r ix e
makeArray (Array r1 ix1 e1 -> Comp
forall r ix e. Strategy r => Array r ix e -> Comp
forall ix e. Array r1 ix e -> Comp
getComp Array r1 ix1 e1
arr1 Comp -> Comp -> Comp
forall a. Semigroup a => a -> a -> a
<> Array r2 ix2 e2 -> Comp
forall r ix e. Strategy r => Array r ix e -> Comp
forall ix e. Array r2 ix e -> Comp
getComp Array r2 ix2 e2
arr2) Sz ix
sz (a -> (ix1 -> e1) -> (ix2 -> e2) -> ix -> e
get a
a (Array r1 ix1 e1 -> ix1 -> e1
forall ix. Index ix => Array r1 ix e1 -> ix -> e1
forall r e ix. (Source r e, Index ix) => Array r ix e -> ix -> e
unsafeIndex Array r1 ix1 e1
arr1) (Array r2 ix2 e2 -> ix2 -> e2
forall ix. Index ix => Array r2 ix e2 -> ix -> e2
forall r e ix. (Source r e, Index ix) => Array r ix e -> ix -> e
unsafeIndex Array r2 ix2 e2
arr2))
  where
    (Sz ix
sz, a
a) = Sz ix1 -> Sz ix2 -> (Sz ix, a)
getSz (Array r1 ix1 e1 -> Sz ix1
forall r ix e. Size r => Array r ix e -> Sz ix
forall ix e. Array r1 ix e -> Sz ix
size Array r1 ix1 e1
arr1) (Array r2 ix2 e2 -> Sz ix2
forall r ix e. Size r => Array r ix e -> Sz ix
forall ix e. Array r2 ix e -> Sz ix
size Array r2 ix2 e2
arr2)
{-# INLINE unsafeTransform2 #-}