{-# LANGUAGE BangPatterns, ExplicitForAll, TypeOperators, MagicHash #-}{-# OPTIONS -fno-warn-orphans #-}moduleData.Array.Repa.Operators.Reduction(foldS,foldP,foldAllS,foldAllP,sumS,sumP,sumAllS,sumAllP,equalsS,equalsP)whereimportData.Array.Repa.BaseimportData.Array.Repa.IndeximportData.Array.Repa.EvalimportData.Array.Repa.Repr.UnboxedimportData.Array.Repa.Operators.MappingasRimportData.Array.Repa.ShapeasSimportqualifiedData.Vector.UnboxedasVimportqualifiedData.Vector.Unboxed.MutableasMimportPreludehiding(sum)importqualifiedData.Array.Repa.Eval.ReductionasEimportSystem.IO.UnsafeimportGHC.Exts-- fold ------------------------------------------------------------------------ | Sequential reduction of the innermost dimension of an arbitrary rank array.---- Combine this with `transpose` to fold any other dimension.foldS::(Shapesh,Elta,Unboxa,Reprra)=>(a->a->a)->a->Arrayr(sh:.Int)a->ArrayUshafoldSfzarr=arr`deepSeqArray`letsh@(sz:.n')=extentarr!(I#n)=n'inunsafePerformIO$domvec<-M.unsafeNew(S.sizesz)E.foldSmvec(\ix->arr`unsafeIndex`fromIndexsh(I#ix))fzn!vec<-V.unsafeFreezemvecnow$fromUnboxedszvec{-# INLINE [1] foldS #-}-- | Parallel reduction of the innermost dimension of an arbitray rank array.---- The first argument needs to be an associative sequential operator.-- The starting element must be neutral with respect to the operator, for-- example @0@ is neutral with respect to @(+)@ as @0 + a = a@.-- These restrictions are required to support parallel evaluation, as the-- starting element may be used multiple times depending on the number of threads.foldP::(Shapesh,Elta,Unboxa,Reprra,Monadm)=>(a->a->a)->a->Arrayr(sh:.Int)a->m(ArrayUsha)foldPfzarr=arr`deepSeqArray`letsh@(sz:.n)=extentarrincaserankshof-- specialise rank-1 arrays, else one thread does all the work.-- We can't match against the shape constructor,-- otherwise type error: (sz ~ Z)--1->dox<-foldAllPfzarrnow$fromUnboxedsz$V.singletonx_->now$unsafePerformIO$domvec<-M.unsafeNew(S.sizesz)E.foldPmvec(\ix->arr`unsafeIndex`fromIndexshix)fzn!vec<-V.unsafeFreezemvecnow$fromUnboxedszvec{-# INLINE [1] foldP #-}-- foldAll ---------------------------------------------------------------------- | Sequential reduction of an array of arbitrary rank to a single scalar value.--foldAllS::(Shapesh,Elta,Unboxa,Reprra)=>(a->a->a)->a->Arrayrsha->afoldAllSfzarr=arr`deepSeqArray`let!ex=extentarr!(I#n)=sizeexinE.foldAllS(\ix->arr`unsafeIndex`fromIndexex(I#ix))fzn{-# INLINE [1] foldAllS #-}-- | Parallel reduction of an array of arbitrary rank to a single scalar value.---- The first argument needs to be an associative sequential operator.-- The starting element must be neutral with respect to the operator,-- for example @0@ is neutral with respect to @(+)@ as @0 + a = a@.-- These restrictions are required to support parallel evaluation, as the-- starting element may be used multiple times depending on the number of threads.foldAllP::(Shapesh,Elta,Unboxa,Reprra,Monadm)=>(a->a->a)->a->Arrayrsha->mafoldAllPfzarr=arr`deepSeqArray`letsh=extentarrn=sizeshinreturn$unsafePerformIO$E.foldAllP(\ix->arr`unsafeIndex`fromIndexshix)fzn{-# INLINE [1] foldAllP #-}-- sum -------------------------------------------------------------------------- | Sequential sum the innermost dimension of an array.sumS::(Shapesh,Numa,Elta,Unboxa,Reprra)=>Arrayr(sh:.Int)a->ArrayUshasumS=foldS(+)0{-# INLINE [3] sumS #-}-- | Parallel sum the innermost dimension of an array.sumP::(Shapesh,Numa,Elta,Unboxa,Reprra,Monadm)=>Arrayr(sh:.Int)a->m(ArrayUsha)sumP=foldP(+)0{-# INLINE [3] sumP #-}-- sumAll ----------------------------------------------------------------------- | Sequential sum of all the elements of an array.sumAllS::(Shapesh,Elta,Unboxa,Numa,Reprra)=>Arrayrsha->asumAllS=foldAllS(+)0{-# INLINE [3] sumAllS #-}-- | Parallel sum all the elements of an array.sumAllP::(Shapesh,Elta,Unboxa,Numa,Reprra,Monadm)=>Arrayrsha->masumAllP=foldAllP(+)0{-# INLINE [3] sumAllP #-}-- Equality ------------------------------------------------------------------instance(Shapesh,Reprre,Eqe)=>Eq(Arrayrshe)where(==)arr1arr2=extentarr1==extentarr2&&(foldAllS(&&)True(R.zipWith(==)arr1arr2))-- | Check whether two arrays have the same shape and contain equal elements,-- in parallel.equalsP::(Shapesh,Reprr1e,Reprr2e,Eqe,Monadm)=>Arrayr1she->Arrayr2she->mBoolequalsParr1arr2=dosame<-foldAllP(&&)True(R.zipWith(==)arr1arr2)return$(extentarr1==extentarr2)&&same-- | Check whether two arrays have the same shape and contain equal elements,-- sequentially.equalsS::(Shapesh,Reprr1e,Reprr2e,Eqe)=>Arrayr1she->Arrayr2she->BoolequalsSarr1arr2=extentarr1==extentarr2&&(foldAllS(&&)True(R.zipWith(==)arr1arr2))