{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Data.Massiv.Array.Ops.Construct
(
empty
, singleton
, replicate
, makeArray
, makeArrayLinear
, makeArrayR
, makeArrayLinearR
, makeVectorR
, iterateN
, iiterateN
, unfoldlS_
, iunfoldlS_
, unfoldrS_
, iunfoldrS_
, makeArrayA
, makeArrayAR
, (...)
, (..:)
, range
, rangeStepM
, rangeStep'
, rangeStep
, rangeInclusive
, rangeStepInclusiveM
, rangeStepInclusive'
, rangeSize
, rangeStepSize
, enumFromN
, enumFromStepN
, expandWithin
, expandWithin'
, expandOuter
, expandInner
) where
import Control.Applicative hiding (empty)
import Control.Monad (void)
import Control.Monad.ST
import Data.Massiv.Array.Delayed.Pull
import Data.Massiv.Array.Delayed.Push
import Data.Massiv.Core.Common
import Prelude as P hiding (enumFromTo, replicate)
makeArrayR :: Construct r ix e => r -> Comp -> Sz ix -> (ix -> e) -> Array r ix e
makeArrayR _ = makeArray
{-# INLINE makeArrayR #-}
makeArrayLinearR :: Construct r ix e => r -> Comp -> Sz ix -> (Int -> e) -> Array r ix e
makeArrayLinearR _ = makeArrayLinear
{-# INLINE makeArrayLinearR #-}
makeVectorR :: Construct r Ix1 e => r -> Comp -> Sz1 -> (Ix1 -> e) -> Array r Ix1 e
makeVectorR _ = makeArray
{-# INLINE makeVectorR #-}
replicate :: forall r ix e . Construct r ix e => Comp -> Sz ix -> e -> Array r ix e
replicate comp sz e = makeArray comp sz (const e)
{-# INLINE replicate #-}
newtype STA r ix a = STA {_runSTA :: forall s. MArray s r ix a -> ST s (Array r ix a)}
runSTA :: Mutable r ix e => Sz ix -> STA r ix e -> Array r ix e
runSTA !sz (STA m) = runST (unsafeNew sz >>= m)
{-# INLINE runSTA #-}
makeArrayA ::
forall r ix e f. (Mutable r ix e, Applicative f)
=> Comp
-> Sz ix
-> (ix -> f e)
-> f (Array r ix e)
makeArrayA !comp !sz f =
let n = totalElem sz
go !i
| i < n =
liftA2
(\e (STA st) -> STA (\ma -> unsafeLinearWrite ma i e >> st ma))
(f (fromLinearIndex sz i))
(go (i + 1))
| otherwise = pure (STA (unsafeFreeze comp))
in runSTA sz <$> go 0
{-# INLINE makeArrayA #-}
makeArrayAR ::
forall r ix e f. (Mutable r ix e, Applicative f)
=> r
-> Comp
-> Sz ix
-> (ix -> f e)
-> f (Array r ix e)
makeArrayAR _ = makeArrayA
{-# INLINE makeArrayAR #-}
iterateN :: forall ix e . Index ix => Comp -> Sz ix -> (e -> e) -> e -> Array DL ix e
iterateN comp sz f = unfoldrS_ comp sz $ \a -> let !a' = f a in (a', a')
{-# INLINE iterateN #-}
iiterateN :: forall ix e . Index ix => Comp -> Sz ix -> (e -> ix -> e) -> e -> Array DL ix e
iiterateN comp sz f = iunfoldrS_ comp sz $ \a ix -> let !a' = f a ix in (a', a')
{-# INLINE iiterateN #-}
unfoldrS_ :: forall ix e a . Construct DL ix e => Comp -> Sz ix -> (a -> (e, a)) -> a -> Array DL ix e
unfoldrS_ comp sz f = iunfoldrS_ comp sz (\a _ -> f a)
{-# INLINE unfoldrS_ #-}
iunfoldrS_
:: Construct DL ix e => Comp -> Sz ix -> (a -> ix -> (e, a)) -> a -> Array DL ix e
iunfoldrS_ comp sz f acc0 =
DLArray
{ dlComp = comp
, dlSize = sz
, dlDefault = Nothing
, dlLoad =
\_ startAt dlWrite ->
void $
loopM startAt (< (totalElem sz + startAt)) (+ 1) acc0 $ \ !i !acc -> do
let (e, acc') = f acc $ fromLinearIndex sz (i - startAt)
dlWrite i e
pure acc'
}
{-# INLINE iunfoldrS_ #-}
unfoldlS_ :: Construct DL ix e => Comp -> Sz ix -> (a -> (a, e)) -> a -> Array DL ix e
unfoldlS_ comp sz f = iunfoldlS_ comp sz (const f)
{-# INLINE unfoldlS_ #-}
iunfoldlS_
:: Construct DL ix e => Comp -> Sz ix -> (ix -> a -> (a, e)) -> a -> Array DL ix e
iunfoldlS_ comp sz f acc0 =
DLArray
{ dlComp = comp
, dlSize = sz
, dlDefault = Nothing
, dlLoad =
\ _ startAt dlWrite ->
void $ loopDeepM startAt (< (totalElem sz + startAt)) (+ 1) acc0 $ \ !i !acc -> do
let (acc', e) = f (fromLinearIndex sz (i - startAt)) acc
dlWrite i e
pure acc'
}
{-# INLINE iunfoldlS_ #-}
infix 4 ..., ..:
(...) :: Index ix => ix -> ix -> Array D ix ix
(...) = rangeInclusive Seq
{-# INLINE (...) #-}
(..:) :: Index ix => ix -> ix -> Array D ix ix
(..:) = range Seq
{-# INLINE (..:) #-}
range :: Index ix => Comp -> ix -> ix -> Array D ix ix
range comp !from !to = rangeSize comp from (Sz (liftIndex2 (-) to from))
{-# INLINE range #-}
rangeStep :: Index ix => Comp -> ix -> ix -> ix -> Maybe (Array D ix ix)
rangeStep = rangeStepM
{-# INLINE rangeStep #-}
{-# DEPRECATED rangeStep "In favor of more general `rangeStepM`" #-}
rangeStepM :: (Index ix, MonadThrow m) =>
Comp
-> ix
-> ix
-> ix
-> m (Array D ix ix)
rangeStepM comp !from !step !to
| foldlIndex (\acc i -> acc || i == 0) False step = throwM $ IndexZeroException step
| otherwise =
let dist = liftIndex2 (-) to from
sz = liftIndex2 div dist step
r = liftIndex signum $ liftIndex2 mod dist step
in pure $ rangeStepSize comp from step (Sz (liftIndex2 (+) sz r))
{-# INLINE rangeStepM #-}
rangeStep' :: Index ix => Comp -> ix -> ix -> ix -> Array D ix ix
rangeStep' comp from step = either throw id . rangeStepM comp from step
{-# INLINE rangeStep' #-}
rangeInclusive :: Index ix => Comp -> ix -> ix -> Array D ix ix
rangeInclusive comp ixFrom ixTo =
rangeSize comp ixFrom (Sz (liftIndex2 (-) (liftIndex (+ 1) ixTo) ixFrom))
{-# INLINE rangeInclusive #-}
rangeStepInclusiveM :: (MonadThrow m, Index ix) => Comp -> ix -> ix -> ix -> m (Array D ix ix)
rangeStepInclusiveM comp ixFrom step ixTo = rangeStepM comp ixFrom step (liftIndex (1 +) ixTo)
{-# INLINE rangeStepInclusiveM #-}
rangeStepInclusive' :: Index ix => Comp -> ix -> ix -> ix -> Array D ix ix
rangeStepInclusive' comp ixFrom step = either throw id . rangeStepInclusiveM comp ixFrom step
{-# INLINE rangeStepInclusive' #-}
rangeSize :: Index ix =>
Comp
-> ix
-> Sz ix
-> Array D ix ix
rangeSize comp !from !sz = makeArray comp sz (liftIndex2 (+) from)
{-# INLINE rangeSize #-}
rangeStepSize :: Index ix =>
Comp
-> ix
-> ix
-> Sz ix
-> Array D ix ix
rangeStepSize comp !from !step !sz =
makeArray comp sz (liftIndex2 (+) from . liftIndex2 (*) step)
{-# INLINE rangeStepSize #-}
enumFromN :: Num e =>
Comp
-> e
-> Sz1
-> Array D Ix1 e
enumFromN comp !from !sz = makeArray comp sz $ \ i -> fromIntegral i + from
{-# INLINE enumFromN #-}
enumFromStepN :: Num e =>
Comp
-> e
-> e
-> Sz1
-> Array D Ix1 e
enumFromStepN comp !from !step !sz = makeArray comp sz $ \ i -> from + fromIntegral i * step
{-# INLINE enumFromStepN #-}
expandWithin ::
forall ix e r n a. (IsIndexDimension ix n, Manifest r (Lower ix) a)
=> Dimension n
-> Int
-> (a -> Int -> e)
-> Array r (Lower ix) a
-> Array D ix e
expandWithin dim k f arr =
makeArray (getComp arr) sz $ \ix ->
let (i, ixl) = pullOutDimension ix dim
in f (unsafeIndex arr ixl) i
where
szl = unSz (size arr)
sz = Sz (insertDimension szl dim k)
{-# INLINE expandWithin #-}
expandWithin'
:: (Index ix, Manifest r (Lower ix) a)
=> Dim
-> Int
-> (a -> Int -> b)
-> Array r (Lower ix) a
-> Array D ix b
expandWithin' dim k f arr =
makeArray (getComp arr) sz $ \ix ->
let (i, ixl) = pullOutDim' ix dim
in f (unsafeIndex arr ixl) i
where
szl = unSz (size arr)
sz = Sz (insertDim' szl dim k)
{-# INLINE expandWithin' #-}
expandOuter
:: (Index ix, Manifest r (Lower ix) a)
=> Int
-> (a -> Int -> b)
-> Array r (Lower ix) a
-> Array D ix b
expandOuter k f arr =
makeArray (getComp arr) sz $ \ix ->
let (i, ixl) = unconsDim ix
in f (unsafeIndex arr ixl) i
where
szl = size arr
sz = consSz (Sz k) szl
{-# INLINE expandOuter #-}
expandInner
:: (Index ix, Manifest r (Lower ix) a)
=> Int
-> (a -> Int -> b)
-> Array r (Lower ix) a
-> Array D ix b
expandInner k f arr =
makeArray (getComp arr) sz $ \ix ->
let (ixl, i) = unsnocDim ix
in f (unsafeIndex arr ixl) i
where
szl = size arr
sz = snocSz szl (Sz k)
{-# INLINE expandInner #-}