packages feed

accelerate-fftw-1.0.3: src/Data/Array/Accelerate/CArray/Conversion.hs

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ConstraintKinds #-}
module Data.Array.Accelerate.CArray.Conversion where

import qualified Data.Array.Accelerate.IO.Foreign.ForeignPtr as AIO
import qualified Data.Array.Accelerate as A
import Data.Array.Accelerate.Sugar.Elt (EltR)
import Data.Array.Accelerate (Array, DIM1, DIM2, Z(Z), (:.)((:.)))

import qualified Data.Array.CArray as CArray
import Data.Array.CArray (CArray, unsafeForeignPtrToCArray, rangeSize)
import Data.Ix (Ix)
import Foreign.Storable.Complex ()

import Data.Array.Accelerate.Data.Complex (Complex)

import System.IO.Unsafe (unsafePerformIO)
import Foreign.ForeignPtr (ForeignPtr, castForeignPtr)
import Foreign.Storable (Storable)


type RealElement a =
      (A.Elt a, Storable a, AIO.ForeignPtrs (EltR a) ~ ForeignPtr a)

type ComplexElement a ac =
      (Storable a, RealFloat a, Complex a ~ ac, A.Elt ac,
       AIO.ForeignPtrs (EltR ac) ~ ForeignPtr a)

accFromCArrayReal1D ::
   (RealElement a) =>
   CArray Int a -> Array DIM1 a
accFromCArrayReal1D arr =
   let (len, fptr) = CArray.toForeignPtr arr
   in  AIO.fromForeignPtrs (Z :. len) fptr

accFromCArrayReal2D ::
   (RealElement a) =>
   CArray (Int, Int) a -> Array DIM2 a
accFromCArrayReal2D arr =
   AIO.fromForeignPtrs
      (accDimsFromArrayBounds2D $ CArray.bounds arr)
      (snd $ CArray.toForeignPtr arr)


accFromCArrayComplex1D ::
   (ComplexElement a ac) =>
   CArray Int (Complex a) -> Array DIM1 (Complex a)
accFromCArrayComplex1D arr =
   accFromCArrayComplex (accDimsFromArrayBounds1D $ CArray.bounds arr) arr

accFromCArrayComplex2D ::
   (ComplexElement a ac) =>
   CArray (Int, Int) (Complex a) -> Array DIM2 (Complex a)
accFromCArrayComplex2D arr =
   accFromCArrayComplex (accDimsFromArrayBounds2D $ CArray.bounds arr) arr

accFromCArrayComplex ::
   (Ix i, A.Shape sh, ComplexElement a ac) =>
   sh -> CArray i ac -> Array sh ac
accFromCArrayComplex sh arr =
   AIO.fromForeignPtrs sh $
   castForeignPtrFromComplex $ snd $ CArray.toForeignPtr arr

castForeignPtrFromComplex :: ForeignPtr (Complex a) -> ForeignPtr a
castForeignPtrFromComplex = castForeignPtr



accDimsFromArrayBounds1D :: (CArray.Ix i) => (i, i) -> DIM1
accDimsFromArrayBounds1D bnds = Z :. rangeSize bnds

accDimsFromArrayBounds2D ::
   (CArray.Ix i, CArray.Ix j) => ((i, j), (i, j)) -> DIM2
accDimsFromArrayBounds2D ((li,lj), (ri,rj)) =
   Z :. rangeSize (li,ri) :. rangeSize (lj,rj)


cArrayFromAccReal1D ::
   (RealElement a) =>
   Array DIM1 a -> CArray Int a
cArrayFromAccReal1D arr =
   let (Z:.len) = A.arrayShape arr
   in  unsafePerformIO $
       unsafeForeignPtrToCArray (AIO.toForeignPtrs arr) (0,len-1)

cArrayFromAccReal2D ::
   (RealElement a) =>
   Array DIM2 a -> CArray (Int, Int) a
cArrayFromAccReal2D arr =
   unsafePerformIO $
   unsafeForeignPtrToCArray (AIO.toForeignPtrs arr)
      (arrayBounds2DFromAccDims $ A.arrayShape arr)

cArrayFromAccComplex1D ::
   (ComplexElement a ac) =>
   Array DIM1 ac -> CArray Int ac
cArrayFromAccComplex1D arr =
   cArrayFromAccComplex
      (arrayBounds1DFromAccDims $ A.arrayShape arr) arr

cArrayFromAccComplex2D ::
   (ComplexElement a ac) =>
   Array DIM2 ac -> CArray (Int,Int) ac
cArrayFromAccComplex2D arr =
   cArrayFromAccComplex
      (arrayBounds2DFromAccDims $ A.arrayShape arr) arr

cArrayFromAccComplex ::
   (Ix i, A.Shape sh, ComplexElement a ac) =>
   (i,i) -> Array sh ac -> CArray i ac
cArrayFromAccComplex bnds arr =
   unsafePerformIO $
   unsafeForeignPtrToCArray
      (castForeignPtrToComplex $ AIO.toForeignPtrs arr) bnds

castForeignPtrToComplex :: ForeignPtr a -> ForeignPtr (Complex a)
castForeignPtrToComplex = castForeignPtr


withCArrayComplex ::
   (Ix i, A.Shape sh, ComplexElement a ac) =>
   (sh -> (i,i)) ->
   (CArray i ac -> CArray i ac) ->
   Array sh ac -> Array sh ac
withCArrayComplex bndsFromSh f arr =
   let sh = A.arrayShape arr
   in  accFromCArrayComplex sh $ f $
       cArrayFromAccComplex (bndsFromSh sh) arr


arrayBounds1DFromAccDims :: DIM1 -> (Int, Int)
arrayBounds1DFromAccDims (Z :. i) = (0, i-1)

arrayBounds2DFromAccDims :: DIM2 -> ((Int, Int), (Int, Int))
arrayBounds2DFromAccDims (Z :. i :. j) = ((0,0), (i-1,j-1))