diff --git a/accelerate-cufft.cabal b/accelerate-cufft.cabal
--- a/accelerate-cufft.cabal
+++ b/accelerate-cufft.cabal
@@ -1,5 +1,5 @@
 Name:             accelerate-cufft
-Version:          0.0.1
+Version:          1.0
 License:          BSD3
 License-File:     LICENSE
 Author:           Henning Thielemann <haskell@henning-thielemann.de>
@@ -20,7 +20,7 @@
   default:     False
 
 Source-Repository this
-  Tag:         0.0.1
+  Tag:         1.0
   Type:        darcs
   Location:    http://hub.darcs.net/thielema/accelerate-cufft/
 
@@ -30,13 +30,13 @@
 
 Library
   Build-Depends:
-    cufft >=0.1.1 && <0.8,
-    cuda >= 0.5 && <0.8,
-    accelerate-fourier >=0.0 && <0.1,
-    accelerate-utility >=0.1 && <0.2,
-    accelerate-cuda >=0.16 && <0.17,
-    accelerate >=0.15 && <0.16,
-    base >=4.5 && <4.10
+    cufft >=0.1.1 && <0.9,
+    cuda >= 0.5 && <0.10,
+    accelerate-fourier >=1.0 && <1.1,
+    accelerate-utility >=1.0 && <1.1,
+    accelerate-llvm-ptx >=1.1 && <1.2,
+    accelerate >=1.1 && <1.2,
+    base >=4.5 && <4.11
 
   GHC-Options:      -Wall -fwarn-missing-import-lists
   Hs-Source-Dirs:   src
@@ -56,7 +56,7 @@
   If flag(buildExamples)
     Build-Depends:
       accelerate-cufft,
-      accelerate-cuda,
+      accelerate-llvm-ptx,
       accelerate,
       base
   Else
@@ -69,7 +69,7 @@
   Default-Language: Haskell98
   If flag(buildExamples)
     Build-Depends:
-      accelerate-cuda,
+      accelerate-llvm-ptx,
       accelerate,
       cufft,
       cuda,
@@ -84,7 +84,7 @@
   Default-Language: Haskell98
   If flag(buildExamples)
     Build-Depends:
-      accelerate-cuda,
+      accelerate-llvm-ptx,
       accelerate,
       cufft,
       cuda,
diff --git a/example/Main.hs b/example/Main.hs
--- a/example/Main.hs
+++ b/example/Main.hs
@@ -2,23 +2,23 @@
 
 import qualified Data.Array.Accelerate.CUFFT.Batched as Batched
 import qualified Data.Array.Accelerate.CUFFT.Single as Single
-import qualified Data.Array.Accelerate.CUDA.Foreign as AF
-import qualified Data.Array.Accelerate.CUDA as CUDA
+import qualified Data.Array.Accelerate.LLVM.PTX as CUDA
 import qualified Data.Array.Accelerate as A
 import Data.Array.Accelerate (Z(Z), (:.)((:.)))
 
 
 mainSingle :: IO ()
 mainSingle = do
+   target <- Batched.getBestTarget
    let dim = Z:.7
-   hf <- AF.inDefaultContext $ Single.plan1D Single.forwardReal dim
+   hf <- Single.plan1D target Single.forwardReal dim
    let spec =
-          CUDA.run1 (Single.transform hf) $
+          CUDA.run1With target (Single.transform hf) $
           A.fromList dim $ 0 : 1 : repeat (0 :: Float)
    print spec
 
-   hb <- AF.inDefaultContext $ Single.plan1D Single.inverseReal dim
-   print $ CUDA.run1 (Single.transform hb) spec
+   hb <- Single.plan1D target Single.inverseReal dim
+   print $ CUDA.run1With target (Single.transform hb) spec
 
 
 mainBatched :: IO ()
@@ -28,16 +28,17 @@
        dim :: A.DIM2
        dim = Z:.count:.width
 
-   hf <- AF.inDefaultContext $ Batched.plan1D Batched.forwardReal dim
+   target <- Batched.getBestTarget
+   hf <- Batched.plan1D target Batched.forwardReal dim
    let spec =
-          CUDA.run1 (Batched.transform hf) $
+          CUDA.run1With target (Batched.transform hf) $
           A.fromList dim $ concat $
           take count $ map (take width) $
           iterate (0:) $ 1 : repeat (0 :: Float)
    print spec
 
-   hb <- AF.inDefaultContext $ Batched.plan1D Batched.inverseReal dim
-   print $ CUDA.run1 (Batched.transform hb) spec
+   hb <- Batched.plan1D target Batched.inverseReal dim
+   print $ CUDA.run1With target (Batched.transform hb) spec
 
 
 main :: IO ()
diff --git a/example/Merged.hs b/example/Merged.hs
--- a/example/Merged.hs
+++ b/example/Merged.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE TypeFamilies #-}
 {- |
 Simple manual implementation
 of embedding cufft functionality in the @accelerate@ framework.
@@ -6,34 +7,50 @@
 -}
 module Main where
 
-import qualified Data.Array.Accelerate.CUDA.Foreign as AF
-import qualified Data.Array.Accelerate.CUDA as CUDA
+import qualified Data.Array.Accelerate.LLVM.PTX.Foreign as AF
+import qualified Data.Array.Accelerate.LLVM.PTX as PTX
+import qualified Data.Array.Accelerate.Array.Sugar as Sugar
 
 import qualified Foreign.CUDA.FFT as CUFFT
+import qualified Foreign.CUDA.Driver as CUDA
+import Foreign.Storable (Storable)
+import Foreign.Ptr (Ptr)
 
 import qualified Data.Array.Accelerate as A
 import Data.Array.Accelerate (Acc, Vector, Z(Z), (:.)((:.)), )
 
 
-transformForeign :: Vector Float -> AF.CIO (Vector Float)
-transformForeign input =
+transformForeign :: AF.Stream -> Vector Float -> AF.LLVM AF.PTX (Vector Float)
+transformForeign stream input =
    let (Z:.inlen) = A.arrayShape input
        outlen = (div inlen 2 + 1) * 2
    in  do
-       output <- AF.allocateArray (Z:.outlen)
-       ((), iptr) <- AF.devicePtrsOfArray input
-       ((), optr) <- AF.devicePtrsOfArray output
-       AF.liftIO $ do
-          h <- CUFFT.plan1D inlen CUFFT.R2C 1
-          CUFFT.execR2C h iptr optr
+       output <- AF.allocateRemote (Z:.outlen)
+       withArray input stream $ \iptr ->
+          withArray output stream $ \optr -> AF.liftIO $ do
+             h <- CUFFT.plan1D inlen CUFFT.R2C 1
+             CUFFT.execR2C h iptr optr
        return output
 
+withArray ::
+   (Sugar.EltRepr e ~ er, AF.ArrayPtrs er ~ Ptr er, Storable er) =>
+   A.Array sh e ->
+   AF.Stream ->
+   (CUDA.DevicePtr er -> AF.LLVM AF.PTX r) ->
+   AF.LLVM AF.PTX r
+withArray (Sugar.Array _ adata) s k =
+   AF.withDevicePtr adata $ \p -> do
+      r <- k p
+      e <- AF.checkpoint s
+      return (Just e, r)
+
+
 transform :: Acc (Vector Float) -> Acc (Vector Float)
 transform =
    A.foreignAcc
-      (AF.CUDAForeignAcc "transformForeign" $ const transformForeign)
+      (AF.ForeignAcc "transformForeign" transformForeign)
       (error "no fft fallback implemented")
 
 main :: IO ()
 main =
-   print $ CUDA.run1 transform $ A.fromList (Z:.5) [1,0,0,0,0]
+   print $ PTX.run1 transform $ A.fromList (Z:.5) [1,0,0,0,0]
diff --git a/example/Separate.hs b/example/Separate.hs
--- a/example/Separate.hs
+++ b/example/Separate.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE TypeFamilies #-}
 {- |
 Simple manual implementation
 of embedding cufft functionality in the @accelerate@ framework.
@@ -6,34 +7,69 @@
 -}
 module Main where
 
-import qualified Data.Array.Accelerate.CUDA.Foreign as AF
-import qualified Data.Array.Accelerate.CUDA as CUDA
+import qualified Data.Array.Accelerate.LLVM.PTX.Foreign as AF
+import qualified Data.Array.Accelerate.LLVM.PTX as PTX
+import qualified Data.Array.Accelerate.Array.Sugar as Sugar
 
 import qualified Foreign.CUDA.FFT as CUFFT
+import qualified Foreign.CUDA.Driver as CUDA
+import Foreign.Storable (Storable)
+import Foreign.Ptr (Ptr)
 
 import qualified Data.Array.Accelerate as A
+import Data.Array.Accelerate.Lifetime (withLifetime)
 import Data.Array.Accelerate (Acc, Vector, Z(Z), (:.)((:.)), )
 
+import Control.Exception (bracket_)
 
-transformForeign :: CUFFT.Handle -> Vector Float -> AF.CIO (Vector Float)
-transformForeign h input =
+
+transformForeign ::
+   CUFFT.Handle -> AF.Stream -> Vector Float -> AF.LLVM AF.PTX (Vector Float)
+transformForeign h stream input =
    let (Z:.inlen) = A.arrayShape input
        outlen = (div inlen 2 + 1) * 2
    in  do
-       output <- AF.allocateArray (Z:.outlen)
-       ((), iptr) <- AF.devicePtrsOfArray input
-       ((), optr) <- AF.devicePtrsOfArray output
-       AF.liftIO $ CUFFT.execR2C h iptr optr
+       output <- AF.allocateRemote (Z:.outlen)
+       withArray input stream $ \iptr ->
+          withArray output stream $ \optr ->
+             AF.liftIO $ CUFFT.execR2C h iptr optr
        return output
 
+withArray ::
+   (Sugar.EltRepr e ~ er, AF.ArrayPtrs er ~ Ptr er, Storable er) =>
+   A.Array sh e ->
+   AF.Stream ->
+   (CUDA.DevicePtr er -> AF.LLVM AF.PTX r) ->
+   AF.LLVM AF.PTX r
+withArray (Sugar.Array _ adata) s k =
+   AF.withDevicePtr adata $ \p -> do
+      r <- k p
+      e <- AF.checkpoint s
+      return (Just e, r)
+
+
 transform :: CUFFT.Handle -> Acc (Vector Float) -> Acc (Vector Float)
 transform h =
    A.foreignAcc
-      (AF.CUDAForeignAcc "transformForeign" $ const $ transformForeign h)
+      (AF.ForeignAcc "transformForeign" $ transformForeign h)
       (error "no fft fallback implemented")
 
+
+getBestTarget :: IO PTX.PTX
+getBestTarget = do
+   CUDA.initialise []
+   dev <- CUDA.device 0
+   prop <- CUDA.props dev
+   PTX.createTargetForDevice dev prop [CUDA.SchedAuto]
+
+atTarget :: PTX.PTX -> IO a -> IO a
+atTarget target act =
+   withLifetime (AF.deviceContext $ AF.ptxContext target) $ \ctx ->
+      bracket_ (CUDA.push ctx) CUDA.pop act
+
 main :: IO ()
 main = do
    let inlen = 5
-   h <- AF.inDefaultContext $ CUFFT.plan1D inlen CUFFT.R2C 1
-   print $ CUDA.run1 (transform h) $ A.fromList (Z:.inlen) [1,0,0,0,0]
+   target <- getBestTarget
+   h <- atTarget target $ CUFFT.plan1D inlen CUFFT.R2C 1
+   print $ PTX.run1With target (transform h) $ A.fromList (Z:.inlen) [1,0,0,0,0]
diff --git a/src/Data/Array/Accelerate/CUFFT/Batched.hs b/src/Data/Array/Accelerate/CUFFT/Batched.hs
--- a/src/Data/Array/Accelerate/CUFFT/Batched.hs
+++ b/src/Data/Array/Accelerate/CUFFT/Batched.hs
@@ -17,14 +17,17 @@
    Priv.forwardComplex, Priv.inverseComplex,
    Priv.forwardReal, Priv.inverseReal,
    Batch0, Batch1, Batch2, Batch3,
+
+   Priv.getBestTarget,
    ) where
 
 import qualified Data.Array.Accelerate.CUFFT.Private as Priv
 import Data.Array.Accelerate.CUFFT.Private
           (Batch0, Batch1, Batch2, Batch3,
-           Mode, wrapFallback, Handle, makeHandle, )
+           Mode, wrapFallback, Handle, makeHandle, atTarget)
 
 import qualified Data.Array.Accelerate.CUFFT.RealClass as RC
+import Data.Array.Accelerate.LLVM.PTX (PTX)
 
 import qualified Data.Array.Accelerate.Fourier.Planned as Fourier
 
@@ -35,24 +38,24 @@
 
 
 {- |
-The plan must be created in the 'Data.Array.Accelerate.CUDA.Context'
+The plan must be created in the 'Data.Array.Accelerate.LLVM.PTX.PTX' target
 where 'Priv.transform' is executed.
-E.g. if you run 'Priv.transform' in 'Data.Array.Accelerate.CUDA.run1',
-then you must call 'plan1D'
-within 'Data.Array.Accelerate.CUDA.Foreign.inDefaultContext'.
+That is, if using cuFFT you always have to use a @run*With@ function.
 -}
 plan1D ::
    (Shape sh, Slice sh, Elt e, RC.Real e) =>
-   Mode (Batch1 sh) e a b -> Batch1 sh -> IO (Handle (Batch1 sh) e a b)
-plan1D mode (batch:.width) =
+   PTX -> Mode (Batch1 sh) e a b -> Batch1 sh -> IO (Handle (Batch1 sh) e a b)
+plan1D target mode (batch:.width) =
+   atTarget target $
    makeHandle mode width
       (\sign -> wrapFallback mode $ Fourier.transform sign width)
       (\typ -> CUFFT.planMany [width] Nothing Nothing typ (A.arraySize batch))
 
 plan2D ::
    (Shape sh, Slice sh, Elt e, RC.Real e) =>
-   Mode (Batch2 sh) e a b -> Batch2 sh -> IO (Handle (Batch2 sh) e a b)
-plan2D mode sh@(batch:.height:.width) =
+   PTX -> Mode (Batch2 sh) e a b -> Batch2 sh -> IO (Handle (Batch2 sh) e a b)
+plan2D target mode sh@(batch:.height:.width) =
+   atTarget target $
    makeHandle mode width
       (wrapFallback mode . Priv.transform2D sh)
       (\typ ->
@@ -60,9 +63,9 @@
 
 plan3D ::
    (Shape sh, Slice sh, Elt e, RC.Real e) =>
-   Mode (Batch3 sh) e a b ->
-   Batch3 sh -> IO (Handle (Batch3 sh) e a b)
-plan3D mode sh@(batch:.depth:.height:.width) =
+   PTX -> Mode (Batch3 sh) e a b -> Batch3 sh -> IO (Handle (Batch3 sh) e a b)
+plan3D target mode sh@(batch:.depth:.height:.width) =
+   atTarget target $
    makeHandle mode width
       (wrapFallback mode . Priv.transform3D sh)
       (\typ ->
diff --git a/src/Data/Array/Accelerate/CUFFT/Private.hs b/src/Data/Array/Accelerate/CUFFT/Private.hs
--- a/src/Data/Array/Accelerate/CUFFT/Private.hs
+++ b/src/Data/Array/Accelerate/CUFFT/Private.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleContexts #-}
 {- |
 Accelerate interface to the native CUDA implementation
 of the Fourier Transform provided by the CUFFT library.
@@ -15,20 +16,24 @@
 import qualified Data.Array.Accelerate.Utility.Sliced as Sliced
 import Data.Array.Accelerate.Utility.Lift.Exp (expr)
 
-import qualified Data.Array.Accelerate.CUDA.Foreign as AF
+import qualified Data.Array.Accelerate.LLVM.PTX.Foreign as AF
+import qualified Data.Array.Accelerate.LLVM.PTX as PTX
+import qualified Data.Array.Accelerate.Array.Sugar as Sugar
 import qualified Data.Array.Accelerate as A
 import Data.Array.Accelerate.Data.Complex (Complex((:+)), real, imag, conjugate)
+import Data.Array.Accelerate.Lifetime (withLifetime)
 import Data.Array.Accelerate
-          (Acc, Array, Elt, Shape, Slice, (:.)((:.)),
-           Exp, (!), (?), (==*), (<*),)
+         (Acc, Array, Elt, Shape, Slice, (:.)((:.)), Exp, (!), (?))
 
 import qualified Foreign.CUDA.FFT as CUFFT
 import qualified Foreign.CUDA.Driver as CUDA
-import Foreign.CUDA.Ptr (DevicePtr, )
+import Foreign.CUDA.Ptr (DevicePtr)
 
 import qualified System.Mem.Weak as Weak
 
+import Control.Exception (bracket_)
 
+
 type Transform sh a b = Acc (Array sh a) -> Acc (Array sh b)
 
 
@@ -55,13 +60,29 @@
    return $ Handle (fallback $ fsign mode) mode width plan
 
 
+
+getBestTarget :: IO AF.PTX
+getBestTarget = do
+   CUDA.initialise []
+   -- (dev,prop) <- PTX.selectBestDevice
+   dev <- CUDA.device 0
+   prop <- CUDA.props dev
+   PTX.createTargetForDevice dev prop [CUDA.SchedAuto]
+
+atTarget :: AF.PTX -> IO a -> IO a
+atTarget target act =
+   withLifetime (AF.deviceContext $ AF.ptxContext target) $ \ctx ->
+      bracket_ (CUDA.push ctx) CUDA.pop act
+
+
+
 type Batch0 sh = sh
 type Batch1 sh = Batch0 sh :. Int
 type Batch2 sh = Batch1 sh :. Int
 type Batch3 sh = Batch2 sh :. Int
 
 transform2D ::
-   (Shape sh, Slice sh, Elt a, RC.Real a) =>
+   (Shape sh, Slice sh, RC.Real a) =>
    Batch2 sh -> Fourier.Sign a ->
    Fourier.Transform (Batch2 sh) (Complex a)
 transform2D (_shape:.height:.width) sign =
@@ -72,7 +93,7 @@
 
 
 transform3D ::
-   (Shape sh, Slice sh, Elt a, RC.Real a) =>
+   (Shape sh, Slice sh, RC.Real a) =>
    Batch3 sh -> Fourier.Sign a ->
    Fourier.Transform (Batch3 sh) (Complex a)
 transform3D (_shape:.depth:.height:.width) sign =
@@ -88,7 +109,7 @@
 The result is un-normalised.
 -}
 transform ::
-   (Shape sh, Slice sh, Elt e, RC.Real e) =>
+   (Shape sh, Slice sh, RC.Real e) =>
    Handle (sh:.Int) e a b ->
    Transform (sh:.Int) a b
 transform hndl@(Handle fallback mode width _) =
@@ -103,7 +124,7 @@
    -}
    wrap mode (A.constant width) $
    A.foreignAcc
-      (AF.CUDAForeignAcc "transformForeign" $ const $ transformForeign hndl)
+      (AF.ForeignAcc "transformForeign" $ transformForeign hndl)
       (unwrap mode (A.constant width) fallback)
 
 
@@ -150,7 +171,11 @@
    Mode {
       types :: CUFFT.Type,
       plainTypes :: Types,
-      execute :: CUFFT.Handle -> CUDA.DevicePtr e -> CUDA.DevicePtr e -> IO (),
+      execute ::
+         CUFFT.Handle ->
+         CUDA.DevicePtr (Sugar.EltRepr e) ->
+         CUDA.DevicePtr (Sugar.EltRepr e) ->
+         IO (),
       wrap :: Exp Int -> Fourier.Transform (sh:.Int) e -> Transform sh a b,
       unwrap :: Exp Int -> Transform sh a b -> Fourier.Transform (sh:.Int) e,
       wrapFallback :: Fourier.Transform sh (Complex e) -> Transform sh a b,
@@ -175,8 +200,8 @@
 
 
 modeC2C ::
-   (Shape sh, Slice sh, RC.Real e, Elt e) =>
-   CUFFT.Type -> ExecuteSign e -> Sign e -> ModeC2C sh e
+   (Shape sh, Slice sh, RC.Real e) =>
+   CUFFT.Type -> ExecuteSign (Sugar.EltRepr e) -> Sign e -> ModeC2C sh e
 modeC2C typ exec (isign,fsign0) =
    ModeC2C $
    Mode {
@@ -203,8 +228,8 @@
 and also for odd data set sizes.
 -}
 modeR2C ::
-   (Shape sh, Slice sh, RC.Real e, Elt e) =>
-   CUFFT.Type -> Execute e -> ModeR2C (sh:.Int) e
+   (Shape sh, Slice sh, RC.Real e) =>
+   CUFFT.Type -> Execute (Sugar.EltRepr e) -> ModeR2C (sh:.Int) e
 modeR2C typ exec =
    ModeR2C $
    Mode {
@@ -218,8 +243,8 @@
    }
 
 modeC2R ::
-   (Shape sh, Slice sh, RC.Real e, Elt e) =>
-   CUFFT.Type -> Execute e -> ModeC2R (sh:.Int) e
+   (Shape sh, Slice sh, RC.Real e) =>
+   CUFFT.Type -> Execute (Sugar.EltRepr e) -> ModeC2R (sh:.Int) e
 modeC2R typ exec =
    ModeC2R $
    Mode {
@@ -234,38 +259,44 @@
 
 
 transformForeign ::
-   (Shape sh, Elt e, RC.Real e) =>
-   Handle (sh:.Int) e a b ->
-   Array (sh:.Int:.Int) e -> AF.CIO (Array (sh:.Int:.Int) e)
-transformForeign (Handle _ mode width hndl) input = do
+   (Shape sh, RC.Real e) =>
+   Handle (sh:.Int) e a b -> AF.Stream ->
+   Array (sh:.Int:.Int) e -> AF.LLVM AF.PTX (Array (sh:.Int:.Int) e)
+transformForeign (Handle _ mode width hndl) stream input = do
    let (shape :. _width :. _tupleSize) = A.arrayShape input
        outputSh =
           case plainTypes mode of
-             R2C -> shape :. div width 2 + 1 :. 2
+             R2C -> shape :. div width 2 + 1 :. (2::Int)
              C2R -> shape :. width :. 1
              C2C -> shape :. width :. 2
-   output <- AF.allocateArray outputSh
-   iptr   <- getDevicePtr input
-   optr   <- getDevicePtr output
-   AF.liftIO $ execute mode hndl iptr optr
-   return output
+   output <- AF.allocateRemote outputSh
+   withDevicePtr input $ \iptr ->
+      withDevicePtr output $ \optr -> do
+         AF.liftIO $ execute mode hndl iptr optr
+         ev <- AF.checkpoint stream
+         return (Just ev, (Just ev, output))
 
 
 newtype
-   GetDevicePtr sh e =
-      GetDevicePtr {
-         runGetDevicePtr :: Array sh e -> AF.CIO ((), CUDA.DevicePtr e)
+   WithDevicePtr target r sh e =
+      WithDevicePtr {
+         runWithDevicePtr ::
+            Array sh e ->
+            (CUDA.DevicePtr (Sugar.EltRepr e) ->
+             AF.LLVM target (Maybe AF.Event, r)) ->
+            AF.LLVM target r
       }
 
-getDevicePtr ::
+withDevicePtr ::
    (RC.Real e) =>
-   Array sh e -> AF.CIO (CUDA.DevicePtr e)
-getDevicePtr =
-   fmap snd .
-   runGetDevicePtr
+   Array sh e ->
+   (CUDA.DevicePtr (Sugar.EltRepr e) -> AF.LLVM AF.PTX (Maybe AF.Event, r)) ->
+   AF.LLVM AF.PTX r
+withDevicePtr =
+   runWithDevicePtr
       (RC.switch
-         (GetDevicePtr AF.devicePtrsOfArray)
-         (GetDevicePtr AF.devicePtrsOfArray))
+         (WithDevicePtr $ \(Sugar.Array _ dat) -> AF.withDevicePtr dat)
+         (WithDevicePtr $ \(Sugar.Array _ dat) -> AF.withDevicePtr dat))
 
 
 {-
@@ -293,7 +324,7 @@
       (A.lift $ A.shape arr :. (2::Int))
       (\ix ->
          let x = arr ! A.indexTail ix
-         in  A.indexHead ix ==* 0 ? (real x, imag x))
+         in  A.indexHead ix A.== 0 ? (real x, imag x))
 
 {-# NOINLINE[1] deinterleave #-}
 deinterleave ::
@@ -324,12 +355,12 @@
 takeHalf width = Sliced.take (div width 2 + 1)
 
 mirror ::
-   (Shape sh, Slice sh, Elt a, A.IsNum a) =>
+   (Shape sh, Slice sh, A.Num a) =>
    Exp Int -> Fourier.Transform (sh:.Int) (Complex a)
 mirror newWidth arr =
    let (sh:.width) = Exp.unlift (expr:.expr) $ A.shape arr
    in  A.generate (A.lift $ sh :. newWidth) $
        Exp.modify (expr:.expr) $ \(ix:.k) ->
-          k <* width ?
+          k A.< width ?
              (arr ! Exp.indexCons ix k,
               conjugate (arr ! Exp.indexCons ix (newWidth - k)))
diff --git a/src/Data/Array/Accelerate/CUFFT/RealClass.hs b/src/Data/Array/Accelerate/CUFFT/RealClass.hs
--- a/src/Data/Array/Accelerate/CUFFT/RealClass.hs
+++ b/src/Data/Array/Accelerate/CUFFT/RealClass.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE FlexibleContexts #-}
 module Data.Array.Accelerate.CUFFT.RealClass where
 
 import qualified Data.Array.Accelerate as A
@@ -6,7 +7,7 @@
 import Prelude (Float, Double)
 
 
-class (P.RealFloat e, A.IsFloating e) => Real e where
+class (P.RealFloat e, A.RealFloat e, A.FromIntegral P.Int e) => Real e where
    switch :: f Float -> f Double -> f e
 
 instance Real Float  where switch f _ = f
diff --git a/src/Data/Array/Accelerate/CUFFT/Single.hs b/src/Data/Array/Accelerate/CUFFT/Single.hs
--- a/src/Data/Array/Accelerate/CUFFT/Single.hs
+++ b/src/Data/Array/Accelerate/CUFFT/Single.hs
@@ -16,44 +16,50 @@
    Mode,
    Priv.forwardComplex, Priv.inverseComplex,
    Priv.forwardReal, Priv.inverseReal,
+
+   Priv.getBestTarget,
    ) 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, )
+          (Mode, wrapFallback, Handle, makeHandle, atTarget)
 
 import qualified Data.Array.Accelerate.Fourier.Planned as Fourier
 
+import Data.Array.Accelerate.LLVM.PTX (PTX)
 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.
+The plan must be created for the target 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) =
+   PTX -> Mode DIM1 e a b -> DIM1 -> IO (Handle DIM1 e a b)
+plan1D target mode (Z:.width) =
+   atTarget target $
    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) =
+   PTX -> Mode DIM2 e a b -> DIM2 -> IO (Handle DIM2 e a b)
+plan2D target mode sh@(Z:.height:.width) =
+   atTarget target $
    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) =
+   PTX -> Mode DIM3 e a b -> DIM3 -> IO (Handle DIM3 e a b)
+plan3D target mode sh@(Z:.depth:.height:.width) =
+   atTarget target $
    makeHandle mode width
       (wrapFallback mode . Priv.transform3D sh)
       (CUFFT.plan3D depth height width)
