{-# LANGUAGE FlexibleContexts, StandaloneDeriving, TypeFamilies #-}
-- | Arrays, based on Data.Vector.Unboxed, indexed by @Point@.
module Game.LambdaHack.Common.PointArray
  ( UnboxRepClass(..), Array(..)
  , empty, (!), accessI, (//), replicateA, unfoldrNA
  , foldrA, foldrA', foldlA', ifoldlA', ifoldrA', foldMA'
  , mapA, imapA, imapMA_, minIndexesA, maxIndexA, maxIndexByA, maxLastIndexA
  , toListA
#ifdef EXPOSE_INTERNAL
    -- * Internal operations
  , toUnboxRep
#endif
  ) where

import Prelude ()

import Game.LambdaHack.Core.Prelude

import           Data.Binary
import           Data.Vector.Binary ()
import qualified Data.Vector.Fusion.Bundle as Bundle
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Unboxed as U

import           Game.LambdaHack.Common.Point
import qualified Game.LambdaHack.Definition.Color as Color
import           Game.LambdaHack.Definition.Defs
import qualified Game.LambdaHack.Definition.DefsInternal as DefsInternal

class ( Ord c, Eq (UnboxRep c), Ord (UnboxRep c), Bounded (UnboxRep c)
      , Binary (UnboxRep c), U.Unbox (UnboxRep c) )
      => UnboxRepClass c where
  type UnboxRep c
  type instance UnboxRep c = c
  toUnboxRepUnsafe :: c -> UnboxRep c  -- has to be total
  fromUnboxRep :: UnboxRep c -> c  -- has to be total

instance UnboxRepClass Bool where
  toUnboxRepUnsafe :: Bool -> UnboxRep Bool
toUnboxRepUnsafe Bool
c = Bool
UnboxRep Bool
c
  fromUnboxRep :: UnboxRep Bool -> Bool
fromUnboxRep UnboxRep Bool
c = Bool
UnboxRep Bool
c

instance UnboxRepClass Word8 where
  toUnboxRepUnsafe :: Word8 -> UnboxRep Word8
toUnboxRepUnsafe Word8
c = Word8
UnboxRep Word8
c
  fromUnboxRep :: UnboxRep Word8 -> Word8
fromUnboxRep UnboxRep Word8
c = Word8
UnboxRep Word8
c

instance UnboxRepClass (ContentId k) where
  type UnboxRep (ContentId k) = Word16
  toUnboxRepUnsafe :: ContentId k -> UnboxRep (ContentId k)
toUnboxRepUnsafe = ContentId k -> UnboxRep (ContentId k)
forall c. ContentId c -> Word16
DefsInternal.fromContentId
  fromUnboxRep :: UnboxRep (ContentId k) -> ContentId k
fromUnboxRep = UnboxRep (ContentId k) -> ContentId k
forall c. Word16 -> ContentId c
DefsInternal.toContentId

instance UnboxRepClass Color.AttrCharW32 where
  type UnboxRep Color.AttrCharW32 = Word32
  toUnboxRepUnsafe :: AttrCharW32 -> UnboxRep AttrCharW32
toUnboxRepUnsafe = AttrCharW32 -> Word32
AttrCharW32 -> UnboxRep AttrCharW32
Color.attrCharW32
  fromUnboxRep :: UnboxRep AttrCharW32 -> AttrCharW32
fromUnboxRep = Word32 -> AttrCharW32
UnboxRep AttrCharW32 -> AttrCharW32
Color.AttrCharW32

-- | Arrays indexed by @Point@.
data Array c = Array
  { Array c -> X
axsize  :: X
  , Array c -> X
aysize  :: Y
  , Array c -> Vector (UnboxRep c)
avector :: U.Vector (UnboxRep c)
  }

deriving instance UnboxRepClass c => Eq (Array c)

instance Show (Array c) where
  show :: Array c -> String
show Array c
a = String
"PointArray.Array with size " String -> ShowS
forall a. [a] -> [a] -> [a]
++ (X, X) -> String
forall a. Show a => a -> String
show (Array c -> X
forall c. Array c -> X
axsize Array c
a, Array c -> X
forall c. Array c -> X
aysize Array c
a)

instance UnboxRepClass c => Binary (Array c) where
  put :: Array c -> Put
put Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} = do
    X -> Put
forall t. Binary t => t -> Put
put X
axsize
    X -> Put
forall t. Binary t => t -> Put
put X
aysize
    Vector (UnboxRep c) -> Put
forall t. Binary t => t -> Put
put Vector (UnboxRep c)
avector
  get :: Get (Array c)
get = do
    X
axsize <- Get X
forall t. Binary t => Get t
get
    X
aysize <- Get X
forall t. Binary t => Get t
get
    Vector (UnboxRep c)
avector <- Get (Vector (UnboxRep c))
forall t. Binary t => Get t
get
    Array c -> Get (Array c)
forall (m :: * -> *) a. Monad m => a -> m a
return (Array c -> Get (Array c)) -> Array c -> Get (Array c)
forall a b. (a -> b) -> a -> b
$! Array :: forall c. X -> X -> Vector (UnboxRep c) -> Array c
Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
..}

toUnboxRep :: UnboxRepClass c => c -> UnboxRep c
{-# INLINE toUnboxRep #-}
toUnboxRep :: c -> UnboxRep c
toUnboxRep c
c =
#ifdef WITH_EXPENSIVE_ASSERTIONS
  Bool -> UnboxRep c -> UnboxRep c
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (c
c c -> c -> Bool
forall a. Ord a => a -> a -> Bool
<= UnboxRep c -> c
forall c. UnboxRepClass c => UnboxRep c -> c
fromUnboxRep UnboxRep c
forall a. Bounded a => a
maxBound) (UnboxRep c -> UnboxRep c) -> UnboxRep c -> UnboxRep c
forall a b. (a -> b) -> a -> b
$
#endif
    c -> UnboxRep c
forall c. UnboxRepClass c => c -> UnboxRep c
toUnboxRepUnsafe c
c

empty :: UnboxRepClass c => Array c
empty :: Array c
empty = X -> X -> Vector (UnboxRep c) -> Array c
forall c. X -> X -> Vector (UnboxRep c) -> Array c
Array X
0 X
0 Vector (UnboxRep c)
forall a. Unbox a => Vector a
U.empty

-- Note: there's no point specializing this to @Point@ arguments,
-- since the extra few additions in @fromPoint@ may be less expensive than
-- memory or register allocations needed for the extra @Int@ in @Point@.
-- | Array lookup.
(!) :: UnboxRepClass c => Array c -> Point -> c
{-# INLINE (!) #-}
(!) Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} Point
p = UnboxRep c -> c
forall c. UnboxRepClass c => UnboxRep c -> c
fromUnboxRep (UnboxRep c -> c) -> UnboxRep c -> c
forall a b. (a -> b) -> a -> b
$ Vector (UnboxRep c)
avector Vector (UnboxRep c) -> X -> UnboxRep c
forall a. Unbox a => Vector a -> X -> a
U.! Point -> X
forall a. Enum a => a -> X
fromEnum Point
p

accessI :: UnboxRepClass c => Array c -> Int -> UnboxRep c
{-# INLINE accessI #-}
accessI :: Array c -> X -> UnboxRep c
accessI Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} X
p = Vector (UnboxRep c)
avector Vector (UnboxRep c) -> X -> UnboxRep c
forall a. Unbox a => Vector a -> X -> a
`U.unsafeIndex` X
p

-- | Construct an array updated with the association list.
(//) :: UnboxRepClass c => Array c -> [(Point, c)] -> Array c
{-# INLINE (//) #-}
// :: Array c -> [(Point, c)] -> Array c
(//) Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} [(Point, c)]
l = let v :: Vector (UnboxRep c)
v = Vector (UnboxRep c)
avector Vector (UnboxRep c) -> [(X, UnboxRep c)] -> Vector (UnboxRep c)
forall a. Unbox a => Vector a -> [(X, a)] -> Vector a
U.// ((Point, c) -> (X, UnboxRep c))
-> [(Point, c)] -> [(X, UnboxRep c)]
forall a b. (a -> b) -> [a] -> [b]
map (Point -> X
forall a. Enum a => a -> X
fromEnum (Point -> X) -> (c -> UnboxRep c) -> (Point, c) -> (X, UnboxRep c)
forall (a :: * -> * -> *) b c b' c'.
Arrow a =>
a b c -> a b' c' -> a (b, b') (c, c')
*** c -> UnboxRep c
forall c. UnboxRepClass c => c -> UnboxRep c
toUnboxRep) [(Point, c)]
l
                   in Array :: forall c. X -> X -> Vector (UnboxRep c) -> Array c
Array{avector :: Vector (UnboxRep c)
avector = Vector (UnboxRep c)
v, X
aysize :: X
axsize :: X
aysize :: X
axsize :: X
..}

-- unsafeUpdateA :: UnboxRepClass c => Array c -> [(Point, c)] -> ()
-- {-# INLINE unsafeUpdateA #-}
-- unsafeUpdateA Array{..} l = runST $ do
--   vThawed <- U.unsafeThaw avector
--   mapM_ (\(p, c) -> VM.write vThawed (fromEnum p) (toUnboxRep c)) l
--   void $ U.unsafeFreeze vThawed

-- unsafeWriteA :: UnboxRepClass c => Array c -> Point -> c -> ()
-- {-# INLINE unsafeWriteA #-}
-- unsafeWriteA Array{..} p c = runST $ do
--   vThawed <- U.unsafeThaw avector
--   VM.write vThawed (fromEnum p) (toUnboxRep c)
--   void $ U.unsafeFreeze vThawed

-- unsafeWriteManyA :: UnboxRepClass c => Array c -> [Point] -> c -> ()
-- {-# INLINE unsafeWriteManyA #-}
-- unsafeWriteManyA Array{..} l c = runST $ do
--   vThawed <- U.unsafeThaw avector
--   let d = toUnboxRep c
--   mapM_ (\p -> VM.write vThawed (fromEnum p) d) l
--   void $ U.unsafeFreeze vThawed

-- | Create an array from a replicated element.
replicateA :: UnboxRepClass c => X -> Y -> c -> Array c
{-# INLINE replicateA #-}
replicateA :: X -> X -> c -> Array c
replicateA X
axsize X
aysize c
c =
  Array :: forall c. X -> X -> Vector (UnboxRep c) -> Array c
Array{avector :: Vector (UnboxRep c)
avector = X -> UnboxRep c -> Vector (UnboxRep c)
forall a. Unbox a => X -> a -> Vector a
U.replicate (X
axsize X -> X -> X
forall a. Num a => a -> a -> a
* X
aysize) (UnboxRep c -> Vector (UnboxRep c))
-> UnboxRep c -> Vector (UnboxRep c)
forall a b. (a -> b) -> a -> b
$ c -> UnboxRep c
forall c. UnboxRepClass c => c -> UnboxRep c
toUnboxRep c
c, X
aysize :: X
axsize :: X
aysize :: X
axsize :: X
..}

-- -- | Create an array from a replicated monadic action.
-- replicateMA :: (Monad m, UnboxRepClass c) => X -> Y -> m c -> m (Array c)
-- {-# INLINE replicateMA #-}
-- replicateMA axsize aysize m = do
--   v <- U.replicateM (axsize * aysize) $ liftM toUnboxRep m
--   return $! Array{avector = v, ..}

-- -- | Create an array from a function.
-- generateA :: UnboxRepClass c => X -> Y -> (Point -> c) -> Array c
-- {-# INLINE generateA #-}
-- generateA axsize aysize f =
--   let g n = toUnboxRep $ f $ toEnum n
--   in Array{avector = U.generate (axsize * aysize) g, ..}

-- -- | Create an array from a monadic function.
-- generateMA :: (Monad m, UnboxRepClass c)
--            => X -> Y -> (Point -> m c) -> m (Array c)
-- {-# INLINE generateMA #-}
-- generateMA axsize aysize fm = do
--   let gm n = liftM toUnboxRep $ fm $ toEnum n
--   v <- U.generateM (axsize * aysize) gm
--   return $! Array{avector = v, ..}

unfoldrNA :: UnboxRepClass c => X -> Y -> (b -> (c, b)) -> b -> Array c
{-# INLINE unfoldrNA #-}
unfoldrNA :: X -> X -> (b -> (c, b)) -> b -> Array c
unfoldrNA X
axsize X
aysize b -> (c, b)
fm b
b =
  let gm :: b -> Maybe (UnboxRep c, b)
gm = (UnboxRep c, b) -> Maybe (UnboxRep c, b)
forall a. a -> Maybe a
Just ((UnboxRep c, b) -> Maybe (UnboxRep c, b))
-> (b -> (UnboxRep c, b)) -> b -> Maybe (UnboxRep c, b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (c -> UnboxRep c) -> (c, b) -> (UnboxRep c, b)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first c -> UnboxRep c
forall c. UnboxRepClass c => c -> UnboxRep c
toUnboxRep ((c, b) -> (UnboxRep c, b))
-> (b -> (c, b)) -> b -> (UnboxRep c, b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> (c, b)
fm
      v :: Vector (UnboxRep c)
v = X -> (b -> Maybe (UnboxRep c, b)) -> b -> Vector (UnboxRep c)
forall a b. Unbox a => X -> (b -> Maybe (a, b)) -> b -> Vector a
U.unfoldrN (X
axsize X -> X -> X
forall a. Num a => a -> a -> a
* X
aysize) b -> Maybe (UnboxRep c, b)
gm b
b
  in Array :: forall c. X -> X -> Vector (UnboxRep c) -> Array c
Array {avector :: Vector (UnboxRep c)
avector = Vector (UnboxRep c)
v, X
aysize :: X
axsize :: X
aysize :: X
axsize :: X
..}

-- -- | Content identifiers array size.
-- sizeA :: Array c -> (X, Y)
-- {-# INLINE sizeA #-}
-- sizeA Array{..} = (axsize, aysize)

-- | Fold right over an array.
foldrA :: UnboxRepClass c => (c -> a -> a) -> a -> Array c -> a
{-# INLINE foldrA #-}
foldrA :: (c -> a -> a) -> a -> Array c -> a
foldrA c -> a -> a
f a
z0 Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} = (UnboxRep c -> a -> a) -> a -> Vector (UnboxRep c) -> a
forall a b. Unbox a => (a -> b -> b) -> b -> Vector a -> b
U.foldr (c -> a -> a
f (c -> a -> a) -> (UnboxRep c -> c) -> UnboxRep c -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnboxRep c -> c
forall c. UnboxRepClass c => UnboxRep c -> c
fromUnboxRep) a
z0 Vector (UnboxRep c)
avector

-- | Fold right strictly over an array.
foldrA' :: UnboxRepClass c => (c -> a -> a) -> a -> Array c -> a
{-# INLINE foldrA' #-}
foldrA' :: (c -> a -> a) -> a -> Array c -> a
foldrA' c -> a -> a
f a
z0 Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} = (UnboxRep c -> a -> a) -> a -> Vector (UnboxRep c) -> a
forall a b. Unbox a => (a -> b -> b) -> b -> Vector a -> b
U.foldr' (c -> a -> a
f (c -> a -> a) -> (UnboxRep c -> c) -> UnboxRep c -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnboxRep c -> c
forall c. UnboxRepClass c => UnboxRep c -> c
fromUnboxRep) a
z0 Vector (UnboxRep c)
avector

-- | Fold left strictly over an array.
foldlA' :: UnboxRepClass c => (a -> c -> a) -> a -> Array c -> a
{-# INLINE foldlA' #-}
foldlA' :: (a -> c -> a) -> a -> Array c -> a
foldlA' a -> c -> a
f a
z0 Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} =
  (a -> UnboxRep c -> a) -> a -> Vector (UnboxRep c) -> a
forall b a. Unbox b => (a -> b -> a) -> a -> Vector b -> a
U.foldl' (\a
a UnboxRep c
c -> a -> c -> a
f a
a (UnboxRep c -> c
forall c. UnboxRepClass c => UnboxRep c -> c
fromUnboxRep UnboxRep c
c)) a
z0 Vector (UnboxRep c)
avector

-- | Fold left strictly over an array
-- (function applied to each element and its index).
ifoldlA' :: UnboxRepClass c => (a -> Point -> c -> a) -> a -> Array c -> a
{-# INLINE ifoldlA' #-}
ifoldlA' :: (a -> Point -> c -> a) -> a -> Array c -> a
ifoldlA' a -> Point -> c -> a
f a
z0 Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} =
  (a -> X -> UnboxRep c -> a) -> a -> Vector (UnboxRep c) -> a
forall b a. Unbox b => (a -> X -> b -> a) -> a -> Vector b -> a
U.ifoldl' (\a
a X
n UnboxRep c
c -> a -> Point -> c -> a
f a
a (X -> Point
forall a. Enum a => X -> a
toEnum X
n) (UnboxRep c -> c
forall c. UnboxRepClass c => UnboxRep c -> c
fromUnboxRep UnboxRep c
c)) a
z0 Vector (UnboxRep c)
avector

-- -- | Fold right over an array
-- -- (function applied to each element and its index).
-- ifoldrA :: UnboxRepClass c => (Point -> c -> a -> a) -> a -> Array c -> a
-- {-# INLINE ifoldrA #-}
-- ifoldrA f z0 Array{..} =
--   U.ifoldr (\n c a -> f (toEnum n) (fromUnboxRep c) a) z0 avector

-- | Fold right strictly over an array
-- (function applied to each element and its index).
ifoldrA' :: UnboxRepClass c => (Point -> c -> a -> a) -> a -> Array c -> a
{-# INLINE ifoldrA' #-}
ifoldrA' :: (Point -> c -> a -> a) -> a -> Array c -> a
ifoldrA' Point -> c -> a -> a
f a
z0 Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} =
  (X -> UnboxRep c -> a -> a) -> a -> Vector (UnboxRep c) -> a
forall a b. Unbox a => (X -> a -> b -> b) -> b -> Vector a -> b
U.ifoldr' (\X
n UnboxRep c
c a
a -> Point -> c -> a -> a
f (X -> Point
forall a. Enum a => X -> a
toEnum X
n) (UnboxRep c -> c
forall c. UnboxRepClass c => UnboxRep c -> c
fromUnboxRep UnboxRep c
c) a
a) a
z0 Vector (UnboxRep c)
avector

-- | Fold monadically strictly over an array.
foldMA' :: (Monad m, UnboxRepClass c) => (a -> c -> m a) -> a -> Array c -> m a
{-# INLINE foldMA' #-}
foldMA' :: (a -> c -> m a) -> a -> Array c -> m a
foldMA' a -> c -> m a
f a
z0 Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} =
  (a -> UnboxRep c -> m a) -> a -> Vector (UnboxRep c) -> m a
forall (m :: * -> *) b a.
(Monad m, Unbox b) =>
(a -> b -> m a) -> a -> Vector b -> m a
U.foldM' (\a
a UnboxRep c
c -> a -> c -> m a
f a
a (UnboxRep c -> c
forall c. UnboxRepClass c => UnboxRep c -> c
fromUnboxRep UnboxRep c
c)) a
z0 Vector (UnboxRep c)
avector

-- -- | Fold monadically strictly over an array
-- -- (function applied to each element and its index).
-- ifoldMA' :: (Monad m, UnboxRepClass c)
--          => (a -> Point -> c -> m a) -> a -> Array c -> m a
-- {-# INLINE ifoldMA' #-}
-- ifoldMA' f z0 Array{..} =
--   U.ifoldM' (\a n c -> f a (toEnum n) (fromUnboxRep c)) z0 avector

-- | Map over an array.
mapA :: (UnboxRepClass c, UnboxRepClass d) => (c -> d) -> Array c -> Array d
{-# INLINE mapA #-}
mapA :: (c -> d) -> Array c -> Array d
mapA c -> d
f Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} =
  Array :: forall c. X -> X -> Vector (UnboxRep c) -> Array c
Array{avector :: Vector (UnboxRep d)
avector = (UnboxRep c -> UnboxRep d)
-> Vector (UnboxRep c) -> Vector (UnboxRep d)
forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
U.map (d -> UnboxRep d
forall c. UnboxRepClass c => c -> UnboxRep c
toUnboxRep (d -> UnboxRep d) -> (UnboxRep c -> d) -> UnboxRep c -> UnboxRep d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. c -> d
f (c -> d) -> (UnboxRep c -> c) -> UnboxRep c -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnboxRep c -> c
forall c. UnboxRepClass c => UnboxRep c -> c
fromUnboxRep) Vector (UnboxRep c)
avector, X
aysize :: X
axsize :: X
aysize :: X
axsize :: X
..}

-- | Map over an array (function applied to each element and its index).
imapA :: (UnboxRepClass c, UnboxRepClass d)
      =>  (Point -> c -> d) -> Array c -> Array d
{-# INLINE imapA #-}
imapA :: (Point -> c -> d) -> Array c -> Array d
imapA Point -> c -> d
f Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} =
  let v :: Vector (UnboxRep d)
v = (X -> UnboxRep c -> UnboxRep d)
-> Vector (UnboxRep c) -> Vector (UnboxRep d)
forall a b.
(Unbox a, Unbox b) =>
(X -> a -> b) -> Vector a -> Vector b
U.imap (\X
n UnboxRep c
c ->
                   d -> UnboxRep d
forall c. UnboxRepClass c => c -> UnboxRep c
toUnboxRep (d -> UnboxRep d) -> d -> UnboxRep d
forall a b. (a -> b) -> a -> b
$ Point -> c -> d
f (X -> Point
forall a. Enum a => X -> a
toEnum X
n) (UnboxRep c -> c
forall c. UnboxRepClass c => UnboxRep c -> c
fromUnboxRep UnboxRep c
c)) Vector (UnboxRep c)
avector
  in Array :: forall c. X -> X -> Vector (UnboxRep c) -> Array c
Array{avector :: Vector (UnboxRep d)
avector = Vector (UnboxRep d)
v, X
aysize :: X
axsize :: X
aysize :: X
axsize :: X
..}

-- | Map monadically over an array (function applied to each element
-- and its index) and ignore the results.
imapMA_ :: (Monad m, UnboxRepClass c) => (Point -> c -> m ()) -> Array c -> m ()
{-# INLINE imapMA_ #-}
imapMA_ :: (Point -> c -> m ()) -> Array c -> m ()
imapMA_ Point -> c -> m ()
f Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} =
  (X -> UnboxRep c -> m ()) -> Vector (UnboxRep c) -> m ()
forall (m :: * -> *) a b.
(Monad m, Unbox a) =>
(X -> a -> m b) -> Vector a -> m ()
U.imapM_ (\X
n UnboxRep c
c -> Point -> c -> m ()
f (X -> Point
forall a. Enum a => X -> a
toEnum X
n) (UnboxRep c -> c
forall c. UnboxRepClass c => UnboxRep c -> c
fromUnboxRep UnboxRep c
c)) Vector (UnboxRep c)
avector

-- -- | Set all elements to the given value, in place.
-- unsafeSetA :: UnboxRepClass c => c -> Array c -> Array c
-- {-# INLINE unsafeSetA #-}
-- unsafeSetA c Array{..} = runST $ do
--   vThawed <- U.unsafeThaw avector
--   VM.set vThawed (toUnboxRep c)
--   vFrozen <- U.unsafeFreeze vThawed
--   return $! Array{avector = vFrozen, ..}

-- -- | Set all elements to the given value, in place, if possible.
-- safeSetA :: UnboxRepClass c => c -> Array c -> Array c
-- {-# INLINE safeSetA #-}
-- safeSetA c Array{..} =
--   Array{avector = U.modify (\v -> VM.set v (toUnboxRep c)) avector, ..}

-- -- | Yield the point coordinates of a minimum element of the array.
-- -- The array may not be empty.
-- minIndexA :: UnboxRepClass c => Array c -> Point
-- {-# INLINE minIndexA #-}
-- minIndexA Array{..} = toEnum $ U.minIndex avector

-- -- | Yield the point coordinates of the last minimum element of the array.
-- -- The array may not be empty.
-- minLastIndexA :: UnboxRepClass c => Array c -> Point
-- {-# INLINE minLastIndexA #-}
-- minLastIndexA Array{..} =
--   toEnum
--   $ fst . Bundle.foldl1' imin . Bundle.indexed . G.stream
--   $ avector
--  where
--   imin (i, x) (j, y) = i `seq` j `seq` if x >= y then (j, y) else (i, x)

-- | Yield the point coordinates of all the minimum elements of the array.
-- The array may not be empty.
minIndexesA :: UnboxRepClass c => Array c -> [Point]
{-# INLINE minIndexesA #-}
minIndexesA :: Array c -> [Point]
minIndexesA Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} =
  ((X, UnboxRep c) -> [Point] -> [Point])
-> [Point] -> Bundle Vector (X, UnboxRep c) -> [Point]
forall a b (v :: * -> *). (a -> b -> b) -> b -> Bundle v a -> b
Bundle.foldr (X, UnboxRep c) -> [Point] -> [Point]
imin [] (Bundle Vector (X, UnboxRep c) -> [Point])
-> (Vector (UnboxRep c) -> Bundle Vector (X, UnboxRep c))
-> Vector (UnboxRep c)
-> [Point]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bundle Vector (UnboxRep c) -> Bundle Vector (X, UnboxRep c)
forall (v :: * -> *) a. Bundle v a -> Bundle v (X, a)
Bundle.indexed (Bundle Vector (UnboxRep c) -> Bundle Vector (X, UnboxRep c))
-> (Vector (UnboxRep c) -> Bundle Vector (UnboxRep c))
-> Vector (UnboxRep c)
-> Bundle Vector (X, UnboxRep c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (UnboxRep c) -> Bundle Vector (UnboxRep c)
forall (v :: * -> *) a. Vector v a => v a -> Bundle v a
G.stream (Vector (UnboxRep c) -> [Point]) -> Vector (UnboxRep c) -> [Point]
forall a b. (a -> b) -> a -> b
$ Vector (UnboxRep c)
avector
 where
  imin :: (X, UnboxRep c) -> [Point] -> [Point]
imin (X
i, UnboxRep c
x) [Point]
acc = if UnboxRep c
x UnboxRep c -> UnboxRep c -> Bool
forall a. Eq a => a -> a -> Bool
== UnboxRep c
minE
                    then let !j :: Point
j = X -> Point
forall a. Enum a => X -> a
toEnum X
i
                         in Point
j Point -> [Point] -> [Point]
forall a. a -> [a] -> [a]
: [Point]
acc
                    else [Point]
acc
  !minE :: UnboxRep c
minE = Vector (UnboxRep c) -> UnboxRep c
forall a. (Unbox a, Ord a) => Vector a -> a
U.minimum Vector (UnboxRep c)
avector

-- | Yield the point coordinates of the first maximum element of the array.
-- The array may not be empty.
maxIndexA :: UnboxRepClass c => Array c -> Point
{-# INLINE maxIndexA #-}
maxIndexA :: Array c -> Point
maxIndexA Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} = X -> Point
forall a. Enum a => X -> a
toEnum (X -> Point) -> X -> Point
forall a b. (a -> b) -> a -> b
$ Vector (UnboxRep c) -> X
forall a. (Unbox a, Ord a) => Vector a -> X
U.maxIndex Vector (UnboxRep c)
avector

-- | Yield the point coordinates of the first maximum element of the array.
-- The array may not be empty.
maxIndexByA :: UnboxRepClass c => (c -> c -> Ordering) -> Array c -> Point
{-# INLINE maxIndexByA #-}
maxIndexByA :: (c -> c -> Ordering) -> Array c -> Point
maxIndexByA c -> c -> Ordering
f Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} =
  let g :: UnboxRep c -> UnboxRep c -> Ordering
g UnboxRep c
a UnboxRep c
b = c -> c -> Ordering
f (UnboxRep c -> c
forall c. UnboxRepClass c => UnboxRep c -> c
fromUnboxRep UnboxRep c
a) (UnboxRep c -> c
forall c. UnboxRepClass c => UnboxRep c -> c
fromUnboxRep UnboxRep c
b)
  in X -> Point
forall a. Enum a => X -> a
toEnum (X -> Point) -> X -> Point
forall a b. (a -> b) -> a -> b
$ (UnboxRep c -> UnboxRep c -> Ordering) -> Vector (UnboxRep c) -> X
forall a. Unbox a => (a -> a -> Ordering) -> Vector a -> X
U.maxIndexBy UnboxRep c -> UnboxRep c -> Ordering
g Vector (UnboxRep c)
avector

-- | Yield the point coordinates of the last maximum element of the array.
-- The array may not be empty.
maxLastIndexA :: UnboxRepClass c => Array c -> Point
{-# INLINE maxLastIndexA #-}
maxLastIndexA :: Array c -> Point
maxLastIndexA Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} =
  X -> Point
forall a. Enum a => X -> a
toEnum
  (X -> Point) -> X -> Point
forall a b. (a -> b) -> a -> b
$ (X, UnboxRep c) -> X
forall a b. (a, b) -> a
fst ((X, UnboxRep c) -> X)
-> (Vector (UnboxRep c) -> (X, UnboxRep c))
-> Vector (UnboxRep c)
-> X
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((X, UnboxRep c) -> (X, UnboxRep c) -> (X, UnboxRep c))
-> Bundle Vector (X, UnboxRep c) -> (X, UnboxRep c)
forall a (v :: * -> *). (a -> a -> a) -> Bundle v a -> a
Bundle.foldl1' (X, UnboxRep c) -> (X, UnboxRep c) -> (X, UnboxRep c)
forall b a. Ord b => (a, b) -> (a, b) -> (a, b)
imax (Bundle Vector (X, UnboxRep c) -> (X, UnboxRep c))
-> (Vector (UnboxRep c) -> Bundle Vector (X, UnboxRep c))
-> Vector (UnboxRep c)
-> (X, UnboxRep c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bundle Vector (UnboxRep c) -> Bundle Vector (X, UnboxRep c)
forall (v :: * -> *) a. Bundle v a -> Bundle v (X, a)
Bundle.indexed (Bundle Vector (UnboxRep c) -> Bundle Vector (X, UnboxRep c))
-> (Vector (UnboxRep c) -> Bundle Vector (UnboxRep c))
-> Vector (UnboxRep c)
-> Bundle Vector (X, UnboxRep c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (UnboxRep c) -> Bundle Vector (UnboxRep c)
forall (v :: * -> *) a. Vector v a => v a -> Bundle v a
G.stream
  (Vector (UnboxRep c) -> X) -> Vector (UnboxRep c) -> X
forall a b. (a -> b) -> a -> b
$ Vector (UnboxRep c)
avector
 where
  imax :: (a, b) -> (a, b) -> (a, b)
imax (a
i, b
x) (a
j, b
y) = a
i a -> (a, b) -> (a, b)
`seq` a
j a -> (a, b) -> (a, b)
`seq` if b
x b -> b -> Bool
forall a. Ord a => a -> a -> Bool
<= b
y then (a
j, b
y) else (a
i, b
x)

-- -- | Force the array not to retain any extra memory.
-- forceA :: UnboxRepClass c => Array c -> Array c
-- {-# INLINE forceA #-}
-- forceA Array{..} = Array{avector = U.force avector, ..}

-- fromListA :: UnboxRepClass c => X -> Y -> [c] -> Array c
-- {-# INLINE fromListA #-}
-- fromListA axsize aysize l =
--   Array{avector = U.fromListN (axsize * aysize) $ map toUnboxRep l, ..}

toListA :: UnboxRepClass c => Array c -> [c]
{-# INLINE toListA #-}
toListA :: Array c -> [c]
toListA Array{X
Vector (UnboxRep c)
avector :: Vector (UnboxRep c)
aysize :: X
axsize :: X
avector :: forall c. Array c -> Vector (UnboxRep c)
aysize :: forall c. Array c -> X
axsize :: forall c. Array c -> X
..} = (UnboxRep c -> c) -> [UnboxRep c] -> [c]
forall a b. (a -> b) -> [a] -> [b]
map UnboxRep c -> c
forall c. UnboxRepClass c => UnboxRep c -> c
fromUnboxRep ([UnboxRep c] -> [c]) -> [UnboxRep c] -> [c]
forall a b. (a -> b) -> a -> b
$ Vector (UnboxRep c) -> [UnboxRep c]
forall a. Unbox a => Vector a -> [a]
U.toList Vector (UnboxRep c)
avector