module Data.Repa.Array.Internals.Bulk ( Bulk (..), BulkI , (!) , length , first, last , toList , toLists , toListss) where import Data.Repa.Array.Internals.Shape import Data.Repa.Array.Internals.Layout import Prelude hiding (length, last) #include "repa-array.h" -- Bulk ----------------------------------------------------------------------- -- | Class of array representations that we can read elements from in a -- random-access manner. class Layout l => Bulk l a where -- | An Array supplies an element of type @a@ to each position in the -- index space associated with layout @l@. data Array l a -- | O(1). Get the layout of an array. layout :: Array l a -> l -- | O(1). Get an element from an array. -- If the provided index is outside the extent of the array then the -- result depends on the layout. index :: Array l a -> Index l -> a -- | Constraint synonym that requires an integer index space. type BulkI l a = (Bulk l a, Index l ~ Int) -- | O(1). Alias for `index`. (!) :: Bulk l a => Array l a -> Index l -> a (!) = index {-# INLINE (!) #-} -- | O(1). Get the number of elements in an array. length :: Bulk l a => Array l a -> Int length !arr = size (extent (layout arr)) {-# INLINE_ARRAY length #-} -- | O(1). Take the first element of an array, if there is one. first :: BulkI l a => Array l a -> Maybe a first !arr = if length arr >= 1 then Just $ index arr 0 else Nothing {-# INLINE first #-} -- O(1). Take the last element of an array, if there is one. last :: BulkI l a => Array l a -> Maybe a last !arr = if length arr >= 1 then Just $ index arr (length arr - 1) else Nothing {-# INLINE last #-} -- Conversion ----------------------------------------------------------------- -- | Convert an array to a list. toList :: Bulk l a => Array l a -> [a] toList !arr = loop_fromList [] 0 where !lo = layout arr !len = length arr loop_fromList !acc !ix | ix >= len = reverse acc | otherwise = let !x = arr `index` (fromIndex lo ix) in loop_fromList (x : acc) (ix + 1) {-# INLINE_ARRAY toList #-} -- | Convert a nested array to some lists. toLists :: ( Bulk l1 (Array l2 a) , Bulk l2 a) => Array l1 (Array l2 a) -- ^ Source array. -> [[a]] -- ^ Result list. toLists arr = let !ll' = toList arr in map toList ll' {-# INLINE_ARRAY toLists #-} -- | Convert a triply nested array to a triply nested list. toListss :: ( Bulk l1 (Array l2 (Array l3 a)) , Bulk l2 (Array l3 a) , Bulk l3 a) => Array l1 (Array l2 (Array l3 a)) -- ^ Source array. -> [[[a]]] -- ^ Result list. toListss arr = let !ll' = toLists arr in map (map toList) ll' {-# INLINE_ARRAY toListss #-}