    {-# LANGUAGE TypeOperators, CPP #-}

    #include "DPH_Header.h"

    import Data.Array.Parallel.Base

    import qualified Prelude as P
    import Prelude ( Eq(..), Num(..), Bool(..), ($), (.) )

    #include "DPH_Interface.h"

    #define ASSERT assert __FILE__ __LINE__

    assert :: P.String -> Int -> Bool -> a -> a
    assert file line False _
      = P.error $ file P.++ " (line " P.++ P.show line P.++ "): assertion failure"
    assert _ _ _ x = x

    class Elt a
    instance Elt a => Elt [a]

    type Array a = [a]
    type SArray a = [[a]]
    type Segd   = ([Int], [Int])

    length = P.length
    empty = []
    replicate = P.replicate
    replicateEach n ns xs
      = ASSERT (n == sum ns)
      . concat
      $ zipWith replicate ns xs
    repeat n xs = concat (replicate n xs)
    (!:) = (P.!!)
    bpermute xs ns = map (xs !:) ns
    (+:+) = (P.++)

    pack xs bs = [x | (x,b) <- P.zip xs bs, b]

    combine [] [] [] = []
    combine (True  : bs) (x : xs) ys       = x : combine bs xs ys
    combine (False : bs) xs       (y : ys) = y : combine bs xs ys

    map = P.map
    zip = P.zipWith (:*:)
    unzip = pairS . P.unzip . P.map unpairS
    fsts = map fstS
    zip3 = P.zipWith3 (\x y z -> x :*: y :*: z)
    unzip3 xs = unzip ys :*: zs
      where
        ys :*: zs = unzip xs
    zipWith = P.zipWith
    zipWith3 = P.zipWith3

    fold = P.foldr -- or equivalently foldl
    fold1 = P.foldr1 -- or equivalently foldr1
    sum = P.sum
    scan f z = P.init . P.scanl f z

    indexed xs = zip [0 .. length xs - 1] xs
    enumFromTo m n = [m .. n]
    enumFromToEach n ps = ASSERT (n == length ns)
                        $ ns
      where
        ns = concat (map (uncurryS enumFromTo) ps)

    randoms n = P.take n . System.Random.randoms
    randomRs n r = P.take n . System.Random.randomRs r

    concat = P.concat
    (ns, is) >: xs = go ns xs
      where
        go [] [] = []
        go (n : ns) xs = let (ys, zs) = P.splitAt n xs
                         in ys : go ns zs

    (^+:+^) = P.zipWith (+:+)

    length_s = P.length
    lengths_s = map length
    indices_s = scan (+) 0 . lengths_s

    fold_s f z = map (fold f z)
    fold1_s f = map (fold1 f)
    sum_s = map sum

    indexed_s = map indexed

    toSegd = unpairS . unzip

    toList x = x
    fromList x = x