diff --git a/Justfile b/Justfile
new file mode 100644
--- /dev/null
+++ b/Justfile
@@ -0,0 +1,9 @@
+run-test:	update-test
+	runhaskell Setup.lhs configure --user --enable-tests
+	runhaskell Setup.lhs build
+	./dist/build/accelerate-fftw-test/accelerate-fftw-test
+
+update-test:
+	doctest-extract-0.1 -i src/ -o test/ \
+	  --import-tested --module-prefix Test --executable-main=Test.hs \
+	  Data.Array.Accelerate.FFTW.Manifest
diff --git a/accelerate-fftw.cabal b/accelerate-fftw.cabal
--- a/accelerate-fftw.cabal
+++ b/accelerate-fftw.cabal
@@ -1,6 +1,7 @@
+Cabal-Version:    2.2
 Name:             accelerate-fftw
-Version:          1.0.2
-License:          BSD3
+Version:          1.0.3
+License:          BSD-3-Clause
 License-File:     LICENSE
 Author:           Henning Thielemann <haskell@henning-thielemann.de>
 Maintainer:       Henning Thielemann <haskell@henning-thielemann.de>
@@ -10,12 +11,13 @@
 Description:
   An interface to the Fastest Fourier Transform in the West (FFTW)
   for the @accelerate@ framework.
-Tested-With:      GHC==7.8.3
-Cabal-Version:    1.14
+Tested-With:      GHC==9.2.8
 Build-Type:       Simple
+Extra-Source-Files:
+  Justfile
 
 Source-Repository this
-  Tag:         1.0.2
+  Tag:         1.0.3
   Type:        darcs
   Location:    https://hub.darcs.net/thielema/accelerate-fftw/
 
@@ -39,3 +41,20 @@
     Data.Array.Accelerate.FFTW.Manifest
   Other-Modules:
     Data.Array.Accelerate.CArray.Conversion
+
+Test-Suite accelerate-fftw-test
+  Type: exitcode-stdio-1.0
+  Build-Depends:
+    doctest-exitcode-stdio >=0.0 && <0.1,
+    doctest-lib >=0.1.1 && <0.2,
+    accelerate-fftw,
+    accelerate-utility >=1.1 && <1.2,
+    accelerate >=1.3 && <1.5,
+    base >=4.5 && <5
+
+  GHC-Options:      -Wall
+  Hs-Source-Dirs:   test
+  Default-Language: Haskell98
+  Main-Is:          Test.hs
+  Other-Modules:
+    Test.Data.Array.Accelerate.FFTW.Manifest
diff --git a/src/Data/Array/Accelerate/CArray/Conversion.hs b/src/Data/Array/Accelerate/CArray/Conversion.hs
--- a/src/Data/Array/Accelerate/CArray/Conversion.hs
+++ b/src/Data/Array/Accelerate/CArray/Conversion.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE ConstraintKinds #-}
 module Data.Array.Accelerate.CArray.Conversion where
 
 import qualified Data.Array.Accelerate.IO.Foreign.ForeignPtr as AIO
@@ -15,19 +16,26 @@
 import Data.Array.Accelerate.Data.Complex (Complex)
 
 import System.IO.Unsafe (unsafePerformIO)
-import Foreign.ForeignPtr (ForeignPtr,)
+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 ::
-   (A.Elt a, Storable a, AIO.ForeignPtrs (EltR a) ~ ForeignPtr a) =>
+   (RealElement a) =>
    CArray Int a -> Array DIM1 a
 accFromCArrayReal1D arr =
    let (len, fptr) = CArray.toForeignPtr arr
    in  AIO.fromForeignPtrs (Z :. len) fptr
 
 accFromCArrayReal2D ::
-   (A.Elt a, Storable a, AIO.ForeignPtrs (EltR a) ~ ForeignPtr a) =>
+   (RealElement a) =>
    CArray (Int, Int) a -> Array DIM2 a
 accFromCArrayReal2D arr =
    AIO.fromForeignPtrs
@@ -36,28 +44,29 @@
 
 
 accFromCArrayComplex1D ::
-   (Storable a, RealFloat a, Complex a ~ ac, A.Elt ac,
-    AIO.ForeignPtrs (EltR ac) ~ ForeignPtr ac) =>
+   (ComplexElement a ac) =>
    CArray Int (Complex a) -> Array DIM1 (Complex a)
 accFromCArrayComplex1D arr =
    accFromCArrayComplex (accDimsFromArrayBounds1D $ CArray.bounds arr) arr
 
 accFromCArrayComplex2D ::
-   (Storable a, RealFloat a, Complex a ~ ac, A.Elt ac,
-    AIO.ForeignPtrs (EltR ac) ~ ForeignPtr ac) =>
+   (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, Storable a, RealFloat a, Complex a ~ ac, A.Elt ac,
-    AIO.ForeignPtrs (EltR ac) ~ ForeignPtr ac) =>
+   (Ix i, A.Shape sh, ComplexElement a ac) =>
    sh -> CArray i ac -> Array sh ac
 accFromCArrayComplex sh arr =
-   AIO.fromForeignPtrs sh (snd $ CArray.toForeignPtr 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
 
@@ -68,7 +77,7 @@
 
 
 cArrayFromAccReal1D ::
-   (A.Elt a, Storable a, AIO.ForeignPtrs (EltR a) ~ ForeignPtr a) =>
+   (RealElement a) =>
    Array DIM1 a -> CArray Int a
 cArrayFromAccReal1D arr =
    let (Z:.len) = A.arrayShape arr
@@ -76,7 +85,7 @@
        unsafeForeignPtrToCArray (AIO.toForeignPtrs arr) (0,len-1)
 
 cArrayFromAccReal2D ::
-   (A.Elt a, Storable a, AIO.ForeignPtrs (EltR a) ~ ForeignPtr a) =>
+   (RealElement a) =>
    Array DIM2 a -> CArray (Int, Int) a
 cArrayFromAccReal2D arr =
    unsafePerformIO $
@@ -84,38 +93,36 @@
       (arrayBounds2DFromAccDims $ A.arrayShape arr)
 
 cArrayFromAccComplex1D ::
-   (Storable a, RealFloat a, Complex a ~ ac, A.Elt ac,
-    AIO.ForeignPtrs (EltR ac) ~ ForeignPtr ac) =>
+   (ComplexElement a ac) =>
    Array DIM1 ac -> CArray Int ac
 cArrayFromAccComplex1D arr =
    cArrayFromAccComplex
       (arrayBounds1DFromAccDims $ A.arrayShape arr) arr
 
 cArrayFromAccComplex2D ::
-   (Storable a, RealFloat a, Complex a ~ ac, A.Elt ac,
-    AIO.ForeignPtrs (EltR ac) ~ ForeignPtr ac) =>
+   (ComplexElement a ac) =>
    Array DIM2 ac -> CArray (Int,Int) ac
 cArrayFromAccComplex2D arr =
    cArrayFromAccComplex
       (arrayBounds2DFromAccDims $ A.arrayShape arr) arr
 
 cArrayFromAccComplex ::
-   (Ix i, A.Shape sh,
-    Storable a, RealFloat a, Complex a ~ ac, A.Elt ac,
-    AIO.ForeignPtrs (EltR ac) ~ ForeignPtr ac) =>
+   (Ix i, A.Shape sh, ComplexElement a ac) =>
    (i,i) -> Array sh ac -> CArray i ac
 cArrayFromAccComplex bnds arr =
    unsafePerformIO $
-   unsafeForeignPtrToCArray (AIO.toForeignPtrs arr) bnds
+   unsafeForeignPtrToCArray
+      (castForeignPtrToComplex $ AIO.toForeignPtrs arr) bnds
 
+castForeignPtrToComplex :: ForeignPtr a -> ForeignPtr (Complex a)
+castForeignPtrToComplex = castForeignPtr
 
+
 withCArrayComplex ::
-   (Ix i, A.Shape sh,
-    Storable a, RealFloat a, Complex a ~ ac, A.Elt ac,
-    AIO.ForeignPtrs (EltR ac) ~ ForeignPtr ac) =>
+   (Ix i, A.Shape sh, ComplexElement a ac) =>
    (sh -> (i,i)) ->
-   (CArray i (Complex a) -> CArray i (Complex a)) ->
-   Array sh (Complex a) -> Array sh (Complex a)
+   (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 $
diff --git a/src/Data/Array/Accelerate/FFTW/Manifest.hs b/src/Data/Array/Accelerate/FFTW/Manifest.hs
--- a/src/Data/Array/Accelerate/FFTW/Manifest.hs
+++ b/src/Data/Array/Accelerate/FFTW/Manifest.hs
@@ -16,47 +16,95 @@
 
 import qualified Data.Array.Accelerate.CArray.Conversion as Conv
 
-import qualified Data.Array.Accelerate.IO.Foreign.ForeignPtr as AIO
-import qualified Data.Array.Accelerate as A
 import qualified Data.Array.Accelerate.Sugar.Shape as Shape
-import Data.Array.Accelerate.Sugar.Elt (EltR)
+import qualified Data.Array.Accelerate as A
 import Data.Array.Accelerate (Array, (:.)((:.)))
 
 import Foreign.Storable.Complex ()
 
 import Data.Array.Accelerate.Data.Complex (Complex)
 
-import Foreign.ForeignPtr (ForeignPtr)
 
+{- $setup
+>>> import qualified Data.Array.Accelerate.Utility.Lift.Exp as Exp
+>>> import qualified Data.Array.Accelerate.Interpreter as AI
+>>> import qualified Data.Array.Accelerate as A
+>>> import Data.Array.Accelerate.Utility.Lift.Exp (expr)
+>>> import Data.Array.Accelerate.Data.Complex (Complex((:+)))
+>>> import Data.Array.Accelerate ((:.)((:.)))
+>>>
+>>> roundComplex :: A.Exp (Complex Float) -> A.Exp (Complex Int)
+>>> roundComplex =
+>>>    Exp.modify (expr:+expr) $ \(r:+i) -> A.round r :+ (A.round i :: A.Exp Int)
+-}
 
+
 type Bounds i = (i,i)
 
 type Transform sh a = Array sh a -> Array sh a
 
-type Element a =
-      (FFTWReal a, A.Elt (Complex a),
-       AIO.ForeignPtrs (EltR (Complex a)) ~ ForeignPtr (Complex a))
+type Element a = (FFTWReal a, Conv.ComplexElement a (Complex a))
 
+{- |
+>>> AI.run1 (A.map roundComplex) $ dft (A.fromList (A.Z:.3:.3) [1000,0,0, 0,1000,0, 0,0,1000])
+Matrix (Z :. 3 :. 3)
+  [ 1000 :+ 0,        1000 :+ 0,        1000 :+ 0,
+    1000 :+ 0, (-500) :+ (-866),    (-500) :+ 866,
+    1000 :+ 0,    (-500) :+ 866, (-500) :+ (-866)]
+-}
 dft ::
    (A.Shape sh, Element a) =>
    Transform (sh:.Int) (Complex a)
 dft = Conv.withCArrayComplex bnds1 $ FFT.dftN [1]
 
+{- |
+>>> AI.run1 (A.map roundComplex) $ idft $ dft (A.fromList (A.Z:.3:.3) [1000,0,0, 0,1000,0, 0,0,1000])
+Matrix (Z :. 3 :. 3)
+  [ 1000 :+ 0,    0 :+ 0,    0 :+ 0,
+       0 :+ 0, 1000 :+ 0,    0 :+ 0,
+       0 :+ 0,    0 :+ 0, 1000 :+ 0]
+-}
 idft ::
    (A.Shape sh, Element a) =>
    Transform (sh:.Int) (Complex a)
-idft = Conv.withCArrayComplex bnds1 $ FFT.dftN [1]
+idft = Conv.withCArrayComplex bnds1 $ FFT.idftN [1]
 
 bnds1 :: (A.Shape sh) => sh:.Int -> Bounds (Int,Int)
 bnds1 (sh:.n) = ((0,0), (Shape.size sh-1, n-1))
 
 
+{- |
+>>> AI.run1 (A.map roundComplex) $ dft2d (A.fromList (A.Z:.3:.3) [1000,0,0, 0,0,0, 0,0,0])
+Matrix (Z :. 3 :. 3)
+  [ 1000 :+ 0, 1000 :+ 0, 1000 :+ 0,
+    1000 :+ 0, 1000 :+ 0, 1000 :+ 0,
+    1000 :+ 0, 1000 :+ 0, 1000 :+ 0]
+
+>>> AI.run1 (A.map roundComplex) $ dft2d (A.fromList (A.Z:.3:.3) [0,1000,0, 0,0,0, 0,0,0])
+Matrix (Z :. 3 :. 3)
+  [ 1000 :+ 0, (-500) :+ (-866), (-500) :+ 866,
+    1000 :+ 0, (-500) :+ (-866), (-500) :+ 866,
+    1000 :+ 0, (-500) :+ (-866), (-500) :+ 866]
+
+>>> AI.run1 (A.map roundComplex) $ dft2d (A.fromList (A.Z:.3:.3) [1000,0,0, 0,1000,0, 0,0,1000])
+Matrix (Z :. 3 :. 3)
+  [ 3000 :+ 0,    0 :+ 0,    0 :+ 0,
+       0 :+ 0,    0 :+ 0, 3000 :+ 0,
+       0 :+ 0, 3000 :+ 0,    0 :+ 0]
+-}
 dft2d ::
    (A.Shape sh, Element a) =>
    Transform (sh:.Int:.Int) (Complex a)
 dft2d =
    Conv.withCArrayComplex bnds2 $ FFT.dftN [1,2]
 
+{- |
+>>> AI.run1 (A.map roundComplex) $ idft2d $ dft2d (A.fromList (A.Z:.3:.3) [1000,0,0, 0,1000,0, 0,0,1000])
+Matrix (Z :. 3 :. 3)
+  [ 1000 :+ 0,    0 :+ 0,    0 :+ 0,
+       0 :+ 0, 1000 :+ 0,    0 :+ 0,
+       0 :+ 0,    0 :+ 0, 1000 :+ 0]
+-}
 idft2d ::
    (A.Shape sh, Element a) =>
    Transform (sh:.Int:.Int) (Complex a)
diff --git a/test/Test.hs b/test/Test.hs
new file mode 100644
--- /dev/null
+++ b/test/Test.hs
@@ -0,0 +1,10 @@
+-- Do not edit! Automatically created with doctest-extract.
+module Main where
+
+import qualified Test.Data.Array.Accelerate.FFTW.Manifest
+
+import qualified Test.DocTest.Driver as DocTest
+
+main :: IO ()
+main = DocTest.run $ do
+    Test.Data.Array.Accelerate.FFTW.Manifest.test
diff --git a/test/Test/Data/Array/Accelerate/FFTW/Manifest.hs b/test/Test/Data/Array/Accelerate/FFTW/Manifest.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Data/Array/Accelerate/FFTW/Manifest.hs
@@ -0,0 +1,65 @@
+-- Do not edit! Automatically created with doctest-extract from src/Data/Array/Accelerate/FFTW/Manifest.hs
+{-# LINE 28 "src/Data/Array/Accelerate/FFTW/Manifest.hs" #-}
+
+module Test.Data.Array.Accelerate.FFTW.Manifest where
+
+import Data.Array.Accelerate.FFTW.Manifest
+import Test.DocTest.Base
+import qualified Test.DocTest.Driver as DocTest
+
+{-# LINE 29 "src/Data/Array/Accelerate/FFTW/Manifest.hs" #-}
+import     qualified Data.Array.Accelerate.Utility.Lift.Exp as Exp
+import     qualified Data.Array.Accelerate.Interpreter as AI
+import     qualified Data.Array.Accelerate as A
+import     Data.Array.Accelerate.Utility.Lift.Exp (expr)
+import     Data.Array.Accelerate.Data.Complex (Complex((:+)))
+import     Data.Array.Accelerate ((:.)((:.)))
+
+roundComplex     :: A.Exp (Complex Float) -> A.Exp (Complex Int)
+roundComplex     =
+       Exp.modify (expr:+expr) $ \(r:+i) -> A.round r :+ (A.round i :: A.Exp Int)
+
+test :: DocTest.T ()
+test = do
+ DocTest.printPrefix "Data.Array.Accelerate.FFTW.Manifest:49: "
+{-# LINE 49 "src/Data/Array/Accelerate/FFTW/Manifest.hs" #-}
+ DocTest.example(
+{-# LINE 49 "src/Data/Array/Accelerate/FFTW/Manifest.hs" #-}
+    AI.run1 (A.map roundComplex) $ dft (A.fromList (A.Z:.3:.3) [1000,0,0, 0,1000,0, 0,0,1000])
+  )
+  [ExpectedLine [LineChunk "Matrix (Z :. 3 :. 3)"],ExpectedLine [LineChunk "  [ 1000 :+ 0,        1000 :+ 0,        1000 :+ 0,"],ExpectedLine [LineChunk "    1000 :+ 0, (-500) :+ (-866),    (-500) :+ 866,"],ExpectedLine [LineChunk "    1000 :+ 0,    (-500) :+ 866, (-500) :+ (-866)]"]]
+ DocTest.printPrefix "Data.Array.Accelerate.FFTW.Manifest:61: "
+{-# LINE 61 "src/Data/Array/Accelerate/FFTW/Manifest.hs" #-}
+ DocTest.example(
+{-# LINE 61 "src/Data/Array/Accelerate/FFTW/Manifest.hs" #-}
+    AI.run1 (A.map roundComplex) $ idft $ dft (A.fromList (A.Z:.3:.3) [1000,0,0, 0,1000,0, 0,0,1000])
+  )
+  [ExpectedLine [LineChunk "Matrix (Z :. 3 :. 3)"],ExpectedLine [LineChunk "  [ 1000 :+ 0,    0 :+ 0,    0 :+ 0,"],ExpectedLine [LineChunk "       0 :+ 0, 1000 :+ 0,    0 :+ 0,"],ExpectedLine [LineChunk "       0 :+ 0,    0 :+ 0, 1000 :+ 0]"]]
+ DocTest.printPrefix "Data.Array.Accelerate.FFTW.Manifest:77: "
+{-# LINE 77 "src/Data/Array/Accelerate/FFTW/Manifest.hs" #-}
+ DocTest.example(
+{-# LINE 77 "src/Data/Array/Accelerate/FFTW/Manifest.hs" #-}
+    AI.run1 (A.map roundComplex) $ dft2d (A.fromList (A.Z:.3:.3) [1000,0,0, 0,0,0, 0,0,0])
+  )
+  [ExpectedLine [LineChunk "Matrix (Z :. 3 :. 3)"],ExpectedLine [LineChunk "  [ 1000 :+ 0, 1000 :+ 0, 1000 :+ 0,"],ExpectedLine [LineChunk "    1000 :+ 0, 1000 :+ 0, 1000 :+ 0,"],ExpectedLine [LineChunk "    1000 :+ 0, 1000 :+ 0, 1000 :+ 0]"]]
+ DocTest.printPrefix "Data.Array.Accelerate.FFTW.Manifest:83: "
+{-# LINE 83 "src/Data/Array/Accelerate/FFTW/Manifest.hs" #-}
+ DocTest.example(
+{-# LINE 83 "src/Data/Array/Accelerate/FFTW/Manifest.hs" #-}
+    AI.run1 (A.map roundComplex) $ dft2d (A.fromList (A.Z:.3:.3) [0,1000,0, 0,0,0, 0,0,0])
+  )
+  [ExpectedLine [LineChunk "Matrix (Z :. 3 :. 3)"],ExpectedLine [LineChunk "  [ 1000 :+ 0, (-500) :+ (-866), (-500) :+ 866,"],ExpectedLine [LineChunk "    1000 :+ 0, (-500) :+ (-866), (-500) :+ 866,"],ExpectedLine [LineChunk "    1000 :+ 0, (-500) :+ (-866), (-500) :+ 866]"]]
+ DocTest.printPrefix "Data.Array.Accelerate.FFTW.Manifest:89: "
+{-# LINE 89 "src/Data/Array/Accelerate/FFTW/Manifest.hs" #-}
+ DocTest.example(
+{-# LINE 89 "src/Data/Array/Accelerate/FFTW/Manifest.hs" #-}
+    AI.run1 (A.map roundComplex) $ dft2d (A.fromList (A.Z:.3:.3) [1000,0,0, 0,1000,0, 0,0,1000])
+  )
+  [ExpectedLine [LineChunk "Matrix (Z :. 3 :. 3)"],ExpectedLine [LineChunk "  [ 3000 :+ 0,    0 :+ 0,    0 :+ 0,"],ExpectedLine [LineChunk "       0 :+ 0,    0 :+ 0, 3000 :+ 0,"],ExpectedLine [LineChunk "       0 :+ 0, 3000 :+ 0,    0 :+ 0]"]]
+ DocTest.printPrefix "Data.Array.Accelerate.FFTW.Manifest:102: "
+{-# LINE 102 "src/Data/Array/Accelerate/FFTW/Manifest.hs" #-}
+ DocTest.example(
+{-# LINE 102 "src/Data/Array/Accelerate/FFTW/Manifest.hs" #-}
+    AI.run1 (A.map roundComplex) $ idft2d $ dft2d (A.fromList (A.Z:.3:.3) [1000,0,0, 0,1000,0, 0,0,1000])
+  )
+  [ExpectedLine [LineChunk "Matrix (Z :. 3 :. 3)"],ExpectedLine [LineChunk "  [ 1000 :+ 0,    0 :+ 0,    0 :+ 0,"],ExpectedLine [LineChunk "       0 :+ 0, 1000 :+ 0,    0 :+ 0,"],ExpectedLine [LineChunk "       0 :+ 0,    0 :+ 0, 1000 :+ 0]"]]
