-----------------------------------------------------------------------------
-- |
-- Module      :  Data.Array.Parallel.Unlifted.Distributed.Basics
-- Copyright   :  (c) 2006 Roman Leshchinskiy
-- License     :  see libraries/ndp/LICENSE
-- 
-- Maintainer  :  Roman Leshchinskiy <rl@cse.unsw.edu.au>
-- Stability   :  experimental
-- Portability :  non-portable (GHC Extensions)
--
-- Basic operations on distributed types.
--


module Data.Array.Parallel.Unlifted.Distributed.Basics (
  eqD, neqD, toD, fromD
) where

import Data.Array.Parallel.Unlifted.Distributed.Gang (
  Gang, gangSize)
import Data.Array.Parallel.Unlifted.Distributed.Types (
  DT, Dist, indexD, newD, writeMD,
  checkGangD)
import Data.Array.Parallel.Unlifted.Distributed.Combinators (
  zipWithD)
import Data.Array.Parallel.Unlifted.Distributed.Scalars (
  andD, orD)

import Control.Monad ( zipWithM_ )

here s = "Data.Array.Parallel.Unlifted.Distributed.Basics." ++ s

-- | Test whether to distributed values are equal. This requires a 'Gang'
-- and hence can't be defined in terms of 'Eq'.
--
eqD :: (Eq a, DT a) => Gang -> Dist a -> Dist a -> Bool
eqD g dx dy = andD g (zipWithD g (==) dx dy)

-- | Test whether to distributed values are not equal. This requires a 'Gang'
-- and hence can't be defined in terms of 'Eq'.
--
neqD :: (Eq a, DT a) => Gang -> Dist a -> Dist a -> Bool
neqD g dx dy = orD g (zipWithD g (/=) dx dy)

-- | Generate a distributed value from the first @p@ elements of a list.
-- 
-- /NOTE:/ Debugging only.
toD :: DT a => Gang -> [a] -> Dist a
toD g xs = newD g (\md -> zipWithM_ (writeMD md) [0 .. gangSize g - 1] xs)

-- | Yield all elements of a distributed value.
--
-- /NOTE:/ Debugging only.
fromD :: DT a => Gang -> Dist a -> [a]
fromD g dt = checkGangD (here "fromDT") g dt $
             map (indexD dt) [0 .. gangSize g - 1]