{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Massiv.Array.Ops.Fold
(
fold
, ifoldMono
, foldMono
, ifoldSemi
, foldSemi
, minimum
, maximum
, sum
, product
, and
, or
, all
, any
, ifoldlInner
, foldlInner
, ifoldrInner
, foldrInner
, ifoldlWithin
, foldlWithin
, ifoldrWithin
, foldrWithin
, ifoldlWithin'
, foldlWithin'
, ifoldrWithin'
, foldrWithin'
, foldlS
, foldrS
, ifoldlS
, ifoldrS
, foldlM
, foldrM
, foldlM_
, foldrM_
, ifoldlM
, ifoldrM
, ifoldlM_
, ifoldrM_
, foldrFB
, lazyFoldlS
, lazyFoldrS
, foldlP
, foldrP
, ifoldlP
, ifoldrP
, foldlOnP
, ifoldlIO
, foldrOnP
, ifoldlOnP
, ifoldrOnP
, ifoldrIO
) where
import Data.Massiv.Array.Delayed.Internal
import Data.Massiv.Array.Ops.Fold.Internal
import Data.Massiv.Array.Ops.Map (imap, map)
import Data.Massiv.Core
import Data.Massiv.Core.Common
import Data.Semigroup
import Prelude hiding (all, and, any,
foldl, foldr, map,
maximum, minimum, or,
product, sum)
ifoldMono ::
(Source r ix e, Monoid m)
=> (ix -> e -> m)
-> Array r ix e
-> m
ifoldMono f = foldlInternal mappend mempty mappend mempty . imap f
{-# INLINE ifoldMono #-}
foldMono ::
(Source r ix e, Monoid m)
=> (e -> m)
-> Array r ix e
-> m
foldMono f = foldlInternal mappend mempty mappend mempty . map f
{-# INLINE foldMono #-}
ifoldSemi ::
(Source r ix e, Semigroup m)
=> (ix -> e -> m)
-> m
-> Array r ix e
-> m
ifoldSemi f m = foldlInternal (<>) m (<>) m . imap f
{-# INLINE ifoldSemi #-}
foldSemi ::
(Source r ix e, Semigroup m)
=> (e -> m)
-> m
-> Array r ix e
-> m
foldSemi f m = foldlInternal (<>) m (<>) m . map f
{-# INLINE foldSemi #-}
ifoldlWithin :: (Index (Lower ix), IsIndexDimension ix n, Source r ix e) =>
Dimension n -> (ix -> a -> e -> a) -> a -> Array r ix e -> Array D (Lower ix) a
ifoldlWithin dim = ifoldlWithin' (fromDimension dim)
{-# INLINE ifoldlWithin #-}
foldlWithin :: (Index (Lower ix), IsIndexDimension ix n, Source r ix e) =>
Dimension n -> (a -> e -> a) -> a -> Array r ix e -> Array D (Lower ix) a
foldlWithin dim f = ifoldlWithin dim (const f)
{-# INLINE foldlWithin #-}
ifoldrWithin :: (Index (Lower ix), IsIndexDimension ix n, Source r ix e) =>
Dimension n -> (ix -> e -> a -> a) -> a -> Array r ix e -> Array D (Lower ix) a
ifoldrWithin dim = ifoldrWithin' (fromDimension dim)
{-# INLINE ifoldrWithin #-}
foldrWithin :: (Index (Lower ix), IsIndexDimension ix n, Source r ix e) =>
Dimension n -> (e -> a -> a) -> a -> Array r ix e -> Array D (Lower ix) a
foldrWithin dim f = ifoldrWithin dim (const f)
{-# INLINE foldrWithin #-}
ifoldlWithin' :: (Index (Lower ix), Source r ix e) =>
Dim -> (ix -> a -> e -> a) -> a -> Array r ix e -> Array D (Lower ix) a
ifoldlWithin' dim f acc0 arr =
unsafeMakeArray (getComp arr) szl $ \ixl ->
iter
(insertDim' ixl dim 0)
(insertDim' ixl dim (k - 1))
(pureIndex 1)
(<=)
acc0
(\ix acc' -> f ix acc' (unsafeIndex arr ix))
where
sz = size arr
(k, szl) = pullOutDim' sz dim
{-# INLINE ifoldlWithin' #-}
foldlWithin' :: (Index (Lower ix), Source r ix e) =>
Dim -> (a -> e -> a) -> a -> Array r ix e -> Array D (Lower ix) a
foldlWithin' dim f = ifoldlWithin' dim (const f)
{-# INLINE foldlWithin' #-}
ifoldrWithin' :: (Index (Lower ix), Source r ix e) =>
Dim -> (ix -> e -> a -> a) -> a -> Array r ix e -> Array D (Lower ix) a
ifoldrWithin' dim f acc0 arr =
unsafeMakeArray (getComp arr) szl $ \ixl ->
iter
(insertDim' ixl dim (k - 1))
(insertDim' ixl dim 0)
(pureIndex (-1))
(>=)
acc0
(\ix acc' -> f ix (unsafeIndex arr ix) acc')
where
sz = size arr
(k, szl) = pullOutDim' sz dim
{-# INLINE ifoldrWithin' #-}
foldrWithin' :: (Index (Lower ix), Source r ix e) =>
Dim -> (e -> a -> a) -> a -> Array r ix e -> Array D (Lower ix) a
foldrWithin' dim f = ifoldrWithin' dim (const f)
{-# INLINE foldrWithin' #-}
ifoldlInner :: (Index (Lower ix), Source r ix e) =>
(ix -> a -> e -> a) -> a -> Array r ix e -> Array D (Lower ix) a
ifoldlInner = ifoldlWithin' 1
{-# INLINE ifoldlInner #-}
foldlInner :: (Index (Lower ix), Source r ix e) =>
(a -> e -> a) -> a -> Array r ix e -> Array D (Lower ix) a
foldlInner = foldlWithin' 1
{-# INLINE foldlInner #-}
ifoldrInner :: (Index (Lower ix), Source r ix e) =>
(ix -> e -> a -> a) -> a -> Array r ix e -> Array D (Lower ix) a
ifoldrInner = ifoldrWithin' 1
{-# INLINE ifoldrInner #-}
foldrInner :: (Index (Lower ix), Source r ix e) =>
(e -> a -> a) -> a -> Array r ix e -> Array D (Lower ix) a
foldrInner = foldrWithin' 1
{-# INLINE foldrInner #-}
maximum :: (Source r ix e, Ord e) =>
Array r ix e -> e
maximum = \arr ->
if isEmpty arr
then error "Data.Massiv.Array.maximum - empty"
else fold max (evaluateAt arr zeroIndex) arr
{-# INLINE maximum #-}
minimum :: (Source r ix e, Ord e) =>
Array r ix e -> e
minimum = \arr ->
if isEmpty arr
then error "Data.Massiv.Array.minimum - empty"
else fold min (evaluateAt arr zeroIndex) arr
{-# INLINE minimum #-}
sum :: (Source r ix e, Num e) =>
Array r ix e -> e
sum = fold (+) 0
{-# INLINE sum #-}
product :: (Source r ix e, Num e) =>
Array r ix e -> e
product = fold (*) 1
{-# INLINE product #-}
and :: (Source r ix Bool) =>
Array r ix Bool -> Bool
and = fold (&&) True
{-# INLINE and #-}
or :: Source r ix Bool =>
Array r ix Bool -> Bool
or = fold (||) False
{-# INLINE or #-}
all :: Source r ix e =>
(e -> Bool) -> Array r ix e -> Bool
all f = foldlInternal (\acc el -> acc && f el) True (&&) True
{-# INLINE all #-}
any :: Source r ix e =>
(e -> Bool) -> Array r ix e -> Bool
any f = foldlInternal (\acc el -> acc || f el) False (||) False
{-# INLINE any #-}