module Data.Array.Accelerate.Array.Representation (
Ix(..), SliceIx(..), SliceIndex(..),
) where
import Data.Array.Accelerate.Type
#include "accelerate.h"
class Eq ix => Ix ix where
dim :: ix -> Int
size :: ix -> Int
intersect :: ix -> ix -> ix
ignore :: ix
index :: ix -> ix -> Int
bound :: ix -> ix -> Boundary e -> Either e ix
iter :: ix -> (ix -> a) -> (a -> a -> a) -> a -> a
rangeToShape :: (ix, ix) -> ix
shapeToRange :: ix -> (ix, ix)
shapeToList :: ix -> [Int]
listToShape :: [Int] -> ix
instance Ix () where
dim () = 0
size () = 1
() `intersect` () = ()
ignore = ()
index () () = 0
bound () () _ = Right ()
iter () f _ _ = f ()
rangeToShape ((), ()) = ()
shapeToRange () = ((), ())
shapeToList () = []
listToShape [] = ()
listToShape _ = error "Data.Array.Accelerate.Array: non-empty list when converting to unit"
instance Ix ix => Ix (ix, Int) where
dim (sh, _) = dim sh + 1
size (sh, sz) = size sh * sz
(sh1, sz1) `intersect` (sh2, sz2) = (sh1 `intersect` sh2, sz1 `min` sz2)
ignore = (ignore, 1)
index (sh, sz) (ix, i) = BOUNDS_CHECK(checkIndex) "index" i sz
$ index sh ix + size sh * i
bound (sh, sz) (ix, i) bndy
| i < 0 = case bndy of
Clamp -> bound sh ix bndy `addDim` 0
Mirror -> bound sh ix bndy `addDim` (i)
Wrap -> bound sh ix bndy `addDim` (szi)
Constant e -> Left e
| i >= sz = case bndy of
Clamp -> bound sh ix bndy `addDim` (sz1)
Mirror -> bound sh ix bndy `addDim` (sz(isz+1))
Wrap -> bound sh ix bndy `addDim` (isz)
Constant e -> Left e
| otherwise = bound sh ix bndy `addDim` i
where
Right ix `addDim` i = Right (ix, i)
Left e `addDim` _ = Left e
iter (sh, sz) f c r = iter' 0
where
iter' i | i >= sz = r
| otherwise = iter sh (\ix -> f (ix, i)) c r `c` iter' (i + 1)
rangeToShape ((sh1, sz1), (sh2, sz2))
= (rangeToShape (sh1, sh2), sz2 sz1 + 1)
shapeToRange (sh, sz)
= let (low, high) = shapeToRange sh
in
((low, 0), (high, sz 1))
shapeToList (sh,sz) = sz : shapeToList sh
listToShape [] = error "Data.Array.Accelerate.Array: empty list when converting to Ix"
listToShape (x:xs) = (listToShape xs,x)
class SliceIx sl where
type Slice sl
type CoSlice sl
type SliceDim sl
sliceIndex :: sl -> SliceIndex sl
(Slice sl)
(CoSlice sl)
(SliceDim sl)
instance SliceIx () where
type Slice () = ()
type CoSlice () = ()
type SliceDim () = ()
sliceIndex _ = SliceNil
instance SliceIx sl => SliceIx (sl, ()) where
type Slice (sl, ()) = (Slice sl, Int)
type CoSlice (sl, ()) = CoSlice sl
type SliceDim (sl, ()) = (SliceDim sl, Int)
sliceIndex _ = SliceAll (sliceIndex (undefined::sl))
instance SliceIx sl => SliceIx (sl, Int) where
type Slice (sl, Int) = Slice sl
type CoSlice (sl, Int) = (CoSlice sl, Int)
type SliceDim (sl, Int) = (SliceDim sl, Int)
sliceIndex _ = SliceFixed (sliceIndex (undefined::sl))
data SliceIndex ix slice coSlice sliceDim where
SliceNil :: SliceIndex () () () ()
SliceAll ::
SliceIndex ix slice co dim -> SliceIndex (ix, ()) (slice, Int) co (dim, Int)
SliceFixed ::
SliceIndex ix slice co dim -> SliceIndex (ix, Int) slice (co, Int) (dim, Int)