{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{- |
Transformations of single datasets.
-}
module Data.Array.Accelerate.CUFFT.Single (
   Priv.Transform,
   Priv.transform,

   Handle,
   plan1D,
   plan2D,
   plan3D,

   RC.Real,
   Mode,
   Priv.forwardComplex, Priv.inverseComplex,
   Priv.forwardReal, Priv.inverseReal,
   ) where

import qualified Data.Array.Accelerate.CUFFT.RealClass as RC
import qualified Data.Array.Accelerate.CUFFT.Private as Priv
import Data.Array.Accelerate.CUFFT.Private
          (Mode, wrapFallback, Handle, makeHandle, )

import qualified Data.Array.Accelerate.Fourier.Planned as Fourier

import Data.Array.Accelerate (Elt, DIM1, DIM2, DIM3, Z(Z), (:.)((:.)), )

import qualified Foreign.CUDA.FFT as CUFFT


{- |
The plan must be created in the context where the transform is executed.
See 'Data.Array.Accelerate.CUFFT.Batched.plan1D' for details.
-}
plan1D ::
   (Elt e, RC.Real e) =>
   Mode DIM1 e a b -> DIM1 -> IO (Handle DIM1 e a b)
plan1D mode (Z:.width) =
   makeHandle mode width
      (\sign -> wrapFallback mode $ Fourier.transform sign width)
      (\typ -> CUFFT.plan1D width typ 1)

plan2D ::
   (Elt e, RC.Real e) =>
   Mode DIM2 e a b -> DIM2 -> IO (Handle DIM2 e a b)
plan2D mode sh@(Z:.height:.width) =
   makeHandle mode width
      (wrapFallback mode . Priv.transform2D sh)
      (CUFFT.plan2D height width)

plan3D ::
   (Elt e, RC.Real e) =>
   Mode DIM3 e a b -> DIM3 -> IO (Handle DIM3 e a b)
plan3D mode sh@(Z:.depth:.height:.width) =
   makeHandle mode width
      (wrapFallback mode . Priv.transform3D sh)
      (CUFFT.plan3D depth height width)