massiv-1.0.5.0: src/Data/Massiv/Array/Manifest.hs
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
-- |
-- Module : Data.Massiv.Array.Manifest
-- Copyright : (c) Alexey Kuleshevich 2018-2022
-- License : BSD3
-- Maintainer : Alexey Kuleshevich <lehins@yandex.ru>
-- Stability : experimental
-- Portability : non-portable
module Data.Massiv.Array.Manifest (
-- * Manifest
Manifest,
-- ** Generate
generateArray,
generateArrayLinear,
generateArrayS,
generateArrayLinearS,
generateSplitSeedArray,
-- ** Stateful worker threads
generateArrayWS,
generateArrayLinearWS,
-- ** Unfold
unfoldrPrimM_,
iunfoldrPrimM_,
unfoldrPrimM,
iunfoldrPrimM,
unfoldlPrimM_,
iunfoldlPrimM_,
unfoldlPrimM,
iunfoldlPrimM,
-- ** Mapping
forPrimM,
forPrimM_,
iforPrimM,
iforPrimM_,
iforLinearPrimM,
iforLinearPrimM_,
for2PrimM_,
ifor2PrimM_,
-- * Boxed
B (..),
BL (..),
BN (..),
N,
pattern N,
Uninitialized (..),
-- ** Access
findIndex,
-- ** Conversion
-- $boxed_conversion_note
toLazyArray,
evalLazyArray,
forceLazyArray,
unwrapNormalForm,
evalNormalForm,
-- *** Primitive Boxed Array
unwrapLazyArray,
wrapLazyArray,
unwrapArray,
evalArray,
unwrapMutableArray,
unwrapMutableLazyArray,
evalMutableArray,
unwrapNormalFormArray,
evalNormalFormArray,
unwrapNormalFormMutableArray,
evalNormalFormMutableArray,
-- *** Boxed Vector
toBoxedVector,
toBoxedMVector,
fromBoxedVector,
fromBoxedMVector,
evalBoxedVector,
evalBoxedMVector,
-- * Primitive
P (..),
Prim,
-- ** Conversion
-- *** Primitive ByteArray
toByteArray,
toByteArrayM,
unwrapByteArray,
unwrapByteArrayOffset,
fromByteArray,
fromByteArrayM,
fromByteArrayOffsetM,
toMutableByteArray,
unwrapMutableByteArray,
unwrapMutableByteArrayOffset,
fromMutableByteArray,
fromMutableByteArrayM,
fromMutableByteArrayOffsetM,
-- *** Primitive Vector
toPrimitiveVector,
toPrimitiveMVector,
fromPrimitiveVector,
fromPrimitiveMVector,
-- * Storable
S (..),
Storable,
mallocCompute,
mallocCopy,
-- ** Conversion
-- *** Storable Vector
toStorableVector,
toStorableMVector,
fromStorableVector,
fromStorableMVector,
-- *** Direct Pointer Access
withPtr,
-- * Unboxed
U (..),
Unbox,
-- ** Conversion
-- *** Unboxed Vector
toUnboxedVector,
toUnboxedMVector,
fromUnboxedVector,
fromUnboxedMVector,
-- * ByteString Conversion
fromByteString,
castFromByteString,
toByteString,
castToByteString,
toBuilder,
castToBuilder,
) where
import Control.Monad
import Data.ByteString as S hiding (findIndex)
import Data.ByteString.Builder
import Data.ByteString.Internal
import Data.ByteString.Unsafe as SU
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
import Data.Massiv.Array.Ops.Fold
import Data.Massiv.Core.Common
import Data.Word (Word8)
-- | /O(n)/ - Convert a strict ByteString into a manifest array. Will return `Nothing` if length
-- doesn't match the total number of elements of new array.
--
-- @since 0.2.1
fromByteString
:: Load r Ix1 Word8
=> Comp
-- ^ Computation strategy
-> ByteString
-- ^ Strict ByteString to use as a source.
-> Vector r Word8
fromByteString comp bs = makeArrayLinear comp (SafeSz (S.length bs)) (SU.unsafeIndex bs)
{-# INLINE fromByteString #-}
{- FOURMOLU_DISABLE -}
-- | /O(n)/ - Convert any source array into a strict `ByteString`. In case when the source array is
-- actually storable, no memory copy will occur.
--
-- @since 0.2.1
toByteString ::
Load r ix Word8
=> Array r ix Word8 -- ^ Source array
-> ByteString
toByteString = castToByteString .
#if __GLASGOW_HASKELL__ >= 820
convert
{- For ghc-8.0 `convert` results in "internal error: ARR_WORDS object entered!" -}
#else
compute
#endif
{-# INLINE toByteString #-}
{- FOURMOLU_ENABLE -}
-- | /O(n)/ - Conversion of array monoidally into a ByteString `Builder`.
--
-- @since 0.2.1
toBuilder :: (Index ix, Source r e) => (e -> Builder) -> Array r ix e -> Builder
toBuilder = foldMono
{-# INLINE toBuilder #-}
-- | /O(1)/ - Cast a storable array of `Word8` to ByteString `Builder`.
--
-- @since 0.5.0
castToBuilder :: Index ix => Array S ix Word8 -> Builder
castToBuilder = byteString . castToByteString
{-# INLINE castToBuilder #-}
-- | /O(1)/ - Cast a `S`torable array into a strict `ByteString`
--
-- @since 0.3.0
castToByteString :: Index ix => Array S ix Word8 -> ByteString
castToByteString = (\(fp, len) -> PS fp 0 len) . unsafeArrayToForeignPtr
{-# INLINE castToByteString #-}
-- | /O(1)/ - Cast a strict `ByteString` into a `S`torable array
--
-- @since 0.3.0
castFromByteString :: Comp -> ByteString -> Vector S Word8
castFromByteString comp (PS fp offset len) = unsafeArrayFromForeignPtr comp fp offset (Sz len)
{-# INLINE castFromByteString #-}
-- $boxed_conversion_note
--
-- Important part of all conversions in this section is that the actual boxed
-- `Data.Primitive.Array.Array`, which holds the pointers to values isn't copied around, it is always
-- kept as the same array. Conversion to Massiv boxed array will undergo evaluation during which
-- computation strategies will be respected.
-- | /O(n)/ - Perform a row-major search starting at @0@ for an element. Returns the index
-- of the first occurance of an element or `Nothing` if a predicate could not be satisifed
-- after it was applyied to all elements of the array.
--
-- @since 0.5.5
findIndex :: (Index ix, Manifest r e) => (e -> Bool) -> Array r ix e -> Maybe ix
findIndex f arr = go 0
where
!sz = size arr
!k = totalElem sz
go !i = do
guard (i < k)
if f (unsafeLinearIndex arr i)
then Just $ fromLinearIndex sz i
else go (i + 1)
{-# INLINE findIndex #-}
-- | Very similar to @`computeAs` `S`@ except load the source array into memory allocated
-- with @malloc@ on C heap. It can potentially be useful when iteroperating with some C
-- programs.
--
-- @since 0.5.9
mallocCompute
:: forall r ix e. (Size r, Load r ix e, Storable e) => Array r ix e -> IO (Array S ix e)
mallocCompute arr = do
let sz = size arr
marr <- unsafeMallocMArray sz
computeInto marr arr
unsafeFreeze (getComp arr) marr
{-# INLINE mallocCompute #-}
-- | Allocate memory on C heap with @malloc@ and copy the source array over.
--
-- @since 0.5.9
mallocCopy :: forall ix e. (Index ix, Storable e) => Array S ix e -> IO (Array S ix e)
mallocCopy arr = do
let sz = size arr
marr <- unsafeMallocMArray sz
unsafeArrayLinearCopy arr 0 marr 0 (SafeSz (totalElem sz))
unsafeFreeze (getComp arr) marr
{-# INLINE mallocCopy #-}