{-# LANGUAGE PArr #-}

-- |
-- Module      :  Data.Array.Parallel
-- Copyright   :  (c) [2006..2007] Manuel M T Chakravarty & Roman Leshchinskiy
-- License     :  see libraries/ndp/LICENSE
-- Maintainer  :  Roman Leshchinskiy <rl@cse.unsw.edu.au>
-- Stability   :  experimental
-- Portability :  non-portable (GHC Extensions)
-- User level interface of parallel arrays.
-- Description ---------------------------------------------------------------
-- Language: Haskell 98 plus parallel arrays
-- The semantic difference between standard Haskell arrays (aka "lazy
-- arrays") and parallel arrays (aka "strict arrays") is that the evaluation
-- of two different elements of a lazy array is independent, whereas in a
-- strict array either non or all elements are evaluated.  In other words,
-- when a parallel array is evaluated to WHNF, all its elements will be
-- evaluated to WHNF.  The name parallel array indicates that all array
-- elements may, in general, be evaluated to WHNF in parallel without any
-- need to resort to speculative evaluation.  This parallel evaluation
-- semantics is also beneficial in the sequential case, as it facilitates
-- loop-based array processing as known from classic array-based languages,
-- such as Fortran.
-- The interface of this module is essentially a variant of the list
-- component of the Prelude, but also includes some functions (such as
-- permutations) that are not provided for lists.  The following list
-- operations are not supported on parallel arrays, as they would require the
-- availability of infinite parallel arrays: `iterate', `repeat', and `cycle'.


{- 		Comments about library structure

	... the final user types ...

  Re-exports Data.Array.Parallel.Unlifted.Parallel

  Parallel operations over UArrs.  No new data types!
  These operations each
	- convert the incoming (UArr t) to a Dist (UArr t)
	- run the operation in parallel using a gang
	- convert the result back to a (UArr t')
  Plus fusion rules, of course!

  Logically: type Dist a = Array GangMember a
	That is, one 'a' per gang member
  Mutable version: MDist

  Element types: unboxed, and products, (), 
		 *and* UArr, SUArr, Segd.
  Provides SUArr, which are segmented UArrs with exactly one nesting level
  Logically: type SUArr a = UArr (UArr a)
  Element types: unboxed, and products and ().

  Again, a mutable version MSUArr is defined internally.

  Provides immutable (UArr) arrays of unboxed
  values, and strict products thereof.

  Simply lifts BUArr to work over strict products (incl unit).
  Internally to Flat, we also define mutable (MUArr) arrays, 
  but they aren't exported.

	.UArr: representation
	.Loop: main loop combinator over UArr, loopU
	.Fusion: fusion rules for loopU
	.Combinators: instantiate loopU (to get fold, scan, map etc)
  The exported maps and folds over these arrays are 
  purely sequential

  Arrays of *unboxed* values, immutable (BUArr t) and mutable (MBUArr
  t), indexed by Int.  Supports slicing (= sub-segment) operations.

  ToDo: combine with UArray and STUArray? (But they are indexed by Ix.)

  ToDo: a common pattern (e.g. when filtering) is that we allocate a
  big mutable array, *partially* fill it, and then want to shrink to
  fixed size when freezing it. (This is needed in Don's ByteString
  library too.)

  Specialised combining functions that specialise loopU to be map, fold, etc
  They are also useful for loopBU; hence not in Unlifted.Flat
  Similar to BUArr, but for strict, boxed values.  
  Representation: Array, STArray.
  Main application: array of UArrs in Distibuted.Types

  A type is "hyperstrict" (in class HS) if evaluating it to WHNF
  produces a result that has no thunks.  It has no methods.  It stops
  you calling a function that would run slowly because of shared 
  thunks in a parallel setting.

module Data.Array.Parallel (
  -- [::],		-- Built-in syntax

  emptyP, singletonP, replicateP, lengthP,
  (+:+), concatP,
  mapP, filterP, combineP, zipP, unzipP,
) where

import GHC.PArr
import Data.Array.Parallel.Prelude.Base.PArr