diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) Henning Thielemann 2021
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name of the author nor the names of his contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/Makefile b/Makefile
new file mode 100644
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,20 @@
+update-foreign:	$(patsubst %, src/Numeric/FFTW/FFI/%.hs, Function Float Double Generic)
+
+src/Numeric/FFTW/FFI/Function.hs:	src/Numeric/FFTW/FFI/Function_tmpl.hs tool/GenerateForeignImport.hs
+	echo "-- Do not edit! Automatically generated by fftw-generate." >$@
+	cat $< >>$@
+	cabal run fftw-generate -v0 -fbuildTools >> $@
+
+src/Numeric/FFTW/FFI/Float.hs:	src/Numeric/FFTW/FFI/Float_tmpl.hs tool/GenerateForeignImport.hs
+	echo "-- Do not edit! Automatically generated by fftw-generate." >$@
+	cat $< >>$@
+	cabal run fftw-generate -v0 -fbuildTools -- Float fftwf >> $@
+
+src/Numeric/FFTW/FFI/Double.hs:	src/Numeric/FFTW/FFI/Double_tmpl.hs tool/GenerateForeignImport.hs
+	echo "-- Do not edit! Automatically generated by fftw-generate." >$@
+	cat $< >>$@
+	cabal run fftw-generate -v0 -fbuildTools -- Double fftw >> $@
+
+src/Numeric/FFTW/FFI/Generic.hs:	src/Numeric/FFTW/FFI/Generic_tmpl.hs tool/GenerateForeignImport.hs
+	echo "-- Do not edit! Automatically generated by fftw-generate." >$@
+	cabal run fftw-generate -v0 -fbuildTools -- --generic $< >> $@
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,3 @@
+#! /usr/bin/env runhaskell
+> import Distribution.Simple
+> main = defaultMain
diff --git a/fftw-ffi.cabal b/fftw-ffi.cabal
new file mode 100644
--- /dev/null
+++ b/fftw-ffi.cabal
@@ -0,0 +1,68 @@
+Cabal-Version:    2.2
+Name:             fftw-ffi
+Version:          0.0
+License:          BSD-3-Clause
+License-File:     LICENSE
+Author:           Henning Thielemann <haskell@henning-thielemann.de>
+Maintainer:       Henning Thielemann <haskell@henning-thielemann.de>
+Homepage:         https://hub.darcs.net/thielema/fftw-ffi/
+Category:         Math
+Synopsis:         Low-level interface to FFTW (Fast Fourier Transform)
+Description:
+  FFTW claims to be the fastest Fourier Transform in the West.
+  This is a low-level interface to @libfftw@.
+  We re-use the type classes from @netlib-ffi@.
+  .
+  See also package @fft@.
+Tested-With:      GHC==7.4.2, GHC==7.8.4, GHC==8.6.5
+Build-Type:       Simple
+Extra-Source-Files:
+  Makefile
+  src/Numeric/FFTW/FFI/Common.h
+
+Flag buildTools
+  Description: Build the Foreign Import generator
+  Manual: True
+  Default: False
+
+Source-Repository this
+  Tag:         0.0
+  Type:        darcs
+  Location:    https://hub.darcs.net/thielema/fftw-ffi/
+
+Source-Repository head
+  Type:        darcs
+  Location:    https://hub.darcs.net/thielema/fftw-ffi/
+
+Library
+  PkgConfig-Depends:
+    fftw3f >=3.3 && <4,
+    fftw3 >=3.3 && <4
+
+  Build-Depends:
+    enumset >=0.0.5 && <0.2,
+    netlib-ffi >=0.0 && <0.2,
+    base >=4.5 && <5
+
+  GHC-Options:      -Wall
+  Hs-Source-Dirs:   src
+  Include-Dirs:     src
+  Default-Language: Haskell98
+  Exposed-Modules:
+    Numeric.FFTW.FFI
+    Numeric.FFTW.FFI.Generic
+    Numeric.FFTW.FFI.Float
+    Numeric.FFTW.FFI.Double
+    Numeric.FFTW.FFI.Type
+    Numeric.FFTW.FFI.Function
+
+Executable fftw-generate
+  If flag(buildTools)
+    Build-Depends:
+      base >=4.5 && <5
+  Else
+    Buildable: False
+
+  GHC-Options:      -Wall
+  Default-Language: Haskell98
+  Main-Is: tool/GenerateForeignImport.hs
diff --git a/src/Numeric/FFTW/FFI.hs b/src/Numeric/FFTW/FFI.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/FFTW/FFI.hs
@@ -0,0 +1,64 @@
+module Numeric.FFTW.FFI (
+   Type.Plan,
+   module Numeric.FFTW.FFI.Generic,
+   ptrDestroyPlan,
+   ptrFree,
+   Type.IODim(..),
+   Type.Flags, Type.Flag,
+   Type.Kind,
+   Type.Sign,
+
+   Type.measure,
+   Type.destroyInput,
+   Type.unaligned,
+   Type.conserveMemory,
+   Type.exhaustive,
+   Type.preserveInput,
+   Type.patient,
+   Type.estimate,
+
+   Type.forward,
+   Type.backward,
+
+   Type.r2hc,
+   Type.hc2r,
+   Type.dht,
+   Type.redft00,
+   Type.redft10,
+   Type.redft01,
+   Type.redft11,
+   Type.rodft00,
+   Type.rodft10,
+   Type.rodft01,
+   Type.rodft11,
+   ) where
+
+import qualified Numeric.FFTW.FFI.Type as Type
+import qualified Numeric.FFTW.FFI.Double as FFTD
+import qualified Numeric.FFTW.FFI.Float  as FFTF
+import Numeric.FFTW.FFI.Generic
+
+import qualified Numeric.Netlib.Class as Class
+
+import Foreign.ForeignPtr (FinalizerPtr)
+import Foreign.Ptr (Ptr)
+
+
+newtype DestroyPlan a =
+   DestroyPlan {runDestroyPlan :: FinalizerPtr (Type.Plan a)}
+
+ptrDestroyPlan :: (Class.Real a) => FinalizerPtr (Type.Plan a)
+ptrDestroyPlan =
+   runDestroyPlan $
+   Class.switchReal
+      (DestroyPlan FFTF.ptrDestroyPlan)
+      (DestroyPlan FFTD.ptrDestroyPlan)
+
+newtype Free a = Free {runFree :: FinalizerPtr (Ptr a)}
+
+ptrFree :: (Class.Real a) => FinalizerPtr (Ptr a)
+ptrFree =
+   runFree $
+   Class.switchReal
+      (Free FFTF.ptrFree)
+      (Free FFTD.ptrFree)
diff --git a/src/Numeric/FFTW/FFI/Common.h b/src/Numeric/FFTW/FFI/Common.h
new file mode 100644
--- /dev/null
+++ b/src/Numeric/FFTW/FFI/Common.h
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+/* cf. FFI cookbook */
+#if __GLASGOW_HASKELL__ < 800
+#define hsc_alignment(t) \
+    printf("(%lu)", (unsigned long)offsetof(struct {char x__; t (y__); }, y__));
+#endif
diff --git a/src/Numeric/FFTW/FFI/Double.hs b/src/Numeric/FFTW/FFI/Double.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/FFTW/FFI/Double.hs
@@ -0,0 +1,156 @@
+-- Do not edit! Automatically generated by fftw-generate.
+{-# LANGUAGE ForeignFunctionInterface #-}
+-- | Using this module requires linking with @-lfftw3@.
+module Numeric.FFTW.FFI.Double where
+
+import qualified Numeric.FFTW.FFI.Function as FFT
+import qualified Numeric.FFTW.FFI.Type as Type
+
+import qualified Data.EnumBitSet as EnumSet
+
+import qualified Foreign.C.Types as C
+import Foreign.ForeignPtr (FinalizerPtr)
+import Foreign.Ptr (Ptr)
+import Foreign.C.String (CString)
+
+
+
+foreign import ccall unsafe "fftw3.h fftw_export_wisdom_to_string"
+   exportWisdomString :: IO CString
+
+foreign import ccall unsafe "fftw3.h fftw_import_wisdom_from_string"
+   importWisdomString :: CString -> IO C.CInt
+
+foreign import ccall unsafe "fftw3.h fftw_import_system_wisdom"
+   importWisdomSystem :: IO C.CInt
+
+
+foreign import ccall safe "fftw3.h &fftw_destroy_plan"
+   ptrDestroyPlan :: FinalizerPtr (Type.Plan Double)
+
+foreign import ccall unsafe "fftw3.h &fftw_free"
+   ptrFree :: FinalizerPtr (Ptr Double)
+
+
+foreign import ccall safe "fftw3.h fftw_plan_dft_1d"
+   planDFT1d :: FFT.PlanDFT1d Double
+
+foreign import ccall safe "fftw3.h fftw_plan_dft_2d"
+   planDFT2d :: FFT.PlanDFT2d Double
+
+foreign import ccall safe "fftw3.h fftw_plan_dft_3d"
+   planDFT3d :: FFT.PlanDFT3d Double
+
+foreign import ccall safe "fftw3.h fftw_plan_dft"
+   planDFT :: FFT.PlanDFT Double
+
+foreign import ccall safe "fftw3.h fftw_plan_dft_r2c_1d"
+   planDFTr2c1d :: FFT.PlanDFTr2c1d Double
+
+foreign import ccall safe "fftw3.h fftw_plan_dft_r2c_2d"
+   planDFTr2c2d :: FFT.PlanDFTr2c2d Double
+
+foreign import ccall safe "fftw3.h fftw_plan_dft_r2c_3d"
+   planDFTr2c3d :: FFT.PlanDFTr2c3d Double
+
+foreign import ccall safe "fftw3.h fftw_plan_dft_r2c"
+   planDFTr2c :: FFT.PlanDFTr2c Double
+
+foreign import ccall safe "fftw3.h fftw_plan_dft_c2r_1d"
+   planDFTc2r1d :: FFT.PlanDFTc2r1d Double
+
+foreign import ccall safe "fftw3.h fftw_plan_dft_c2r_2d"
+   planDFTc2r2d :: FFT.PlanDFTc2r2d Double
+
+foreign import ccall safe "fftw3.h fftw_plan_dft_c2r_3d"
+   planDFTc2r3d :: FFT.PlanDFTc2r3d Double
+
+foreign import ccall safe "fftw3.h fftw_plan_dft_c2r"
+   planDFTc2r :: FFT.PlanDFTc2r Double
+
+foreign import ccall safe "fftw3.h fftw_plan_r2r_1d"
+   planR2r1d :: FFT.PlanR2r1d Double
+
+foreign import ccall safe "fftw3.h fftw_plan_r2r_2d"
+   planR2r2d :: FFT.PlanR2r2d Double
+
+foreign import ccall safe "fftw3.h fftw_plan_r2r_3d"
+   planR2r3d :: FFT.PlanR2r3d Double
+
+foreign import ccall safe "fftw3.h fftw_plan_r2r"
+   planR2r :: FFT.PlanR2r Double
+
+foreign import ccall safe "fftw3.h fftw_plan_many_dft"
+   planManyDFT :: FFT.PlanManyDFT Double
+
+foreign import ccall safe "fftw3.h fftw_plan_many_dft_r2c"
+   planManyDFTr2c :: FFT.PlanManyDFTr2c Double
+
+foreign import ccall safe "fftw3.h fftw_plan_many_dft_c2r"
+   planManyDFTc2r :: FFT.PlanManyDFTc2r Double
+
+foreign import ccall safe "fftw3.h fftw_plan_many_r2r"
+   planManyR2r :: FFT.PlanManyR2r Double
+
+foreign import ccall safe "fftw3.h fftw_plan_guru_dft"
+   planGuruDFT :: FFT.PlanGuruDFT Double
+
+foreign import ccall safe "fftw3.h fftw_plan_guru_dft_r2c"
+   planGuruDFTr2c :: FFT.PlanGuruDFTr2c Double
+
+foreign import ccall safe "fftw3.h fftw_plan_guru_dft_c2r"
+   planGuruDFTc2r :: FFT.PlanGuruDFTc2r Double
+
+foreign import ccall safe "fftw3.h fftw_plan_guru_r2r"
+   planGuruR2r :: FFT.PlanGuruR2r Double
+
+foreign import ccall safe "fftw3.h fftw_plan_guru_split_dft"
+   planGuruSplitDFT :: FFT.PlanGuruSplitDFT Double
+
+foreign import ccall safe "fftw3.h fftw_plan_guru_split_dft_r2c"
+   planGuruSplitDFTr2c :: FFT.PlanGuruSplitDFTr2c Double
+
+foreign import ccall safe "fftw3.h fftw_plan_guru_split_dft_c2r"
+   planGuruSplitDFTc2r :: FFT.PlanGuruSplitDFTc2r Double
+
+foreign import ccall safe "fftw3.h fftw_destroy_plan"
+   destroyPlan :: FFT.DestroyPlan Double
+
+foreign import ccall safe "fftw3.h fftw_execute"
+   execute :: FFT.Execute Double
+
+foreign import ccall safe "fftw3.h fftw_execute_dft"
+   executeDFT :: FFT.ExecuteDFT Double
+
+foreign import ccall safe "fftw3.h fftw_execute_dft_r2c"
+   executeDFTr2c :: FFT.ExecuteDFTr2c Double
+
+foreign import ccall safe "fftw3.h fftw_execute_dft_c2r"
+   executeDFTc2r :: FFT.ExecuteDFTc2r Double
+
+foreign import ccall safe "fftw3.h fftw_execute_r2r"
+   executeR2r :: FFT.ExecuteR2r Double
+
+foreign import ccall safe "fftw3.h fftw_execute_split_dft"
+   executeSplitDFT :: FFT.ExecuteSplitDFT Double
+
+foreign import ccall safe "fftw3.h fftw_execute_split_dft_r2c"
+   executeSplitDFTr2c :: FFT.ExecuteSplitDFTr2c Double
+
+foreign import ccall safe "fftw3.h fftw_execute_split_dft_c2r"
+   executeSplitDFTc2r :: FFT.ExecuteSplitDFTc2r Double
+
+foreign import ccall unsafe "fftw3.h fftw_malloc"
+   malloc :: FFT.Malloc Double
+
+foreign import ccall unsafe "fftw3.h fftw_free"
+   free :: FFT.Free Double
+
+foreign import ccall unsafe "fftw3.h fftw_alloc_real"
+   allocReal :: FFT.AllocReal Double
+
+foreign import ccall unsafe "fftw3.h fftw_alloc_complex"
+   allocComplex :: FFT.AllocComplex Double
+
+foreign import ccall unsafe "fftw3.h fftw_free"
+   freeComplex :: FFT.FreeComplex Double
diff --git a/src/Numeric/FFTW/FFI/Float.hs b/src/Numeric/FFTW/FFI/Float.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/FFTW/FFI/Float.hs
@@ -0,0 +1,156 @@
+-- Do not edit! Automatically generated by fftw-generate.
+{-# LANGUAGE ForeignFunctionInterface #-}
+-- | Using this module requires linking with @-lfftw3f@.
+module Numeric.FFTW.FFI.Float where
+
+import qualified Numeric.FFTW.FFI.Function as FFT
+import qualified Numeric.FFTW.FFI.Type as Type
+
+import qualified Data.EnumBitSet as EnumSet
+
+import qualified Foreign.C.Types as C
+import Foreign.ForeignPtr (FinalizerPtr)
+import Foreign.Ptr (Ptr)
+import Foreign.C.String (CString)
+
+
+
+foreign import ccall unsafe "fftw3.h fftwf_export_wisdom_to_string"
+   exportWisdomString :: IO CString
+
+foreign import ccall unsafe "fftw3.h fftwf_import_wisdom_from_string"
+   importWisdomString :: CString -> IO C.CInt
+
+foreign import ccall unsafe "fftw3.h fftwf_import_system_wisdom"
+   importWisdomSystem :: IO C.CInt
+
+
+foreign import ccall safe "fftw3.h &fftwf_destroy_plan"
+   ptrDestroyPlan :: FinalizerPtr (Type.Plan Float)
+
+foreign import ccall unsafe "fftw3.h &fftwf_free"
+   ptrFree :: FinalizerPtr (Ptr Float)
+
+
+foreign import ccall safe "fftw3.h fftwf_plan_dft_1d"
+   planDFT1d :: FFT.PlanDFT1d Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_dft_2d"
+   planDFT2d :: FFT.PlanDFT2d Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_dft_3d"
+   planDFT3d :: FFT.PlanDFT3d Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_dft"
+   planDFT :: FFT.PlanDFT Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_dft_r2c_1d"
+   planDFTr2c1d :: FFT.PlanDFTr2c1d Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_dft_r2c_2d"
+   planDFTr2c2d :: FFT.PlanDFTr2c2d Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_dft_r2c_3d"
+   planDFTr2c3d :: FFT.PlanDFTr2c3d Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_dft_r2c"
+   planDFTr2c :: FFT.PlanDFTr2c Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_dft_c2r_1d"
+   planDFTc2r1d :: FFT.PlanDFTc2r1d Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_dft_c2r_2d"
+   planDFTc2r2d :: FFT.PlanDFTc2r2d Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_dft_c2r_3d"
+   planDFTc2r3d :: FFT.PlanDFTc2r3d Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_dft_c2r"
+   planDFTc2r :: FFT.PlanDFTc2r Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_r2r_1d"
+   planR2r1d :: FFT.PlanR2r1d Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_r2r_2d"
+   planR2r2d :: FFT.PlanR2r2d Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_r2r_3d"
+   planR2r3d :: FFT.PlanR2r3d Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_r2r"
+   planR2r :: FFT.PlanR2r Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_many_dft"
+   planManyDFT :: FFT.PlanManyDFT Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_many_dft_r2c"
+   planManyDFTr2c :: FFT.PlanManyDFTr2c Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_many_dft_c2r"
+   planManyDFTc2r :: FFT.PlanManyDFTc2r Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_many_r2r"
+   planManyR2r :: FFT.PlanManyR2r Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_guru_dft"
+   planGuruDFT :: FFT.PlanGuruDFT Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_guru_dft_r2c"
+   planGuruDFTr2c :: FFT.PlanGuruDFTr2c Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_guru_dft_c2r"
+   planGuruDFTc2r :: FFT.PlanGuruDFTc2r Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_guru_r2r"
+   planGuruR2r :: FFT.PlanGuruR2r Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_guru_split_dft"
+   planGuruSplitDFT :: FFT.PlanGuruSplitDFT Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_guru_split_dft_r2c"
+   planGuruSplitDFTr2c :: FFT.PlanGuruSplitDFTr2c Float
+
+foreign import ccall safe "fftw3.h fftwf_plan_guru_split_dft_c2r"
+   planGuruSplitDFTc2r :: FFT.PlanGuruSplitDFTc2r Float
+
+foreign import ccall safe "fftw3.h fftwf_destroy_plan"
+   destroyPlan :: FFT.DestroyPlan Float
+
+foreign import ccall safe "fftw3.h fftwf_execute"
+   execute :: FFT.Execute Float
+
+foreign import ccall safe "fftw3.h fftwf_execute_dft"
+   executeDFT :: FFT.ExecuteDFT Float
+
+foreign import ccall safe "fftw3.h fftwf_execute_dft_r2c"
+   executeDFTr2c :: FFT.ExecuteDFTr2c Float
+
+foreign import ccall safe "fftw3.h fftwf_execute_dft_c2r"
+   executeDFTc2r :: FFT.ExecuteDFTc2r Float
+
+foreign import ccall safe "fftw3.h fftwf_execute_r2r"
+   executeR2r :: FFT.ExecuteR2r Float
+
+foreign import ccall safe "fftw3.h fftwf_execute_split_dft"
+   executeSplitDFT :: FFT.ExecuteSplitDFT Float
+
+foreign import ccall safe "fftw3.h fftwf_execute_split_dft_r2c"
+   executeSplitDFTr2c :: FFT.ExecuteSplitDFTr2c Float
+
+foreign import ccall safe "fftw3.h fftwf_execute_split_dft_c2r"
+   executeSplitDFTc2r :: FFT.ExecuteSplitDFTc2r Float
+
+foreign import ccall unsafe "fftw3.h fftwf_malloc"
+   malloc :: FFT.Malloc Float
+
+foreign import ccall unsafe "fftw3.h fftwf_free"
+   free :: FFT.Free Float
+
+foreign import ccall unsafe "fftw3.h fftwf_alloc_real"
+   allocReal :: FFT.AllocReal Float
+
+foreign import ccall unsafe "fftw3.h fftwf_alloc_complex"
+   allocComplex :: FFT.AllocComplex Float
+
+foreign import ccall unsafe "fftw3.h fftwf_free"
+   freeComplex :: FFT.FreeComplex Float
diff --git a/src/Numeric/FFTW/FFI/Function.hs b/src/Numeric/FFTW/FFI/Function.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/FFTW/FFI/Function.hs
@@ -0,0 +1,192 @@
+-- Do not edit! Automatically generated by fftw-generate.
+module Numeric.FFTW.FFI.Function where
+
+import Numeric.FFTW.FFI.Type (Plan, IODim, Sign, Flags, Kind)
+
+import qualified Foreign.C.Types as C
+import Foreign.Ptr (Ptr)
+
+import Data.Complex (Complex)
+
+
+type PlanDFT1d a =
+   C.CInt ->
+   Ptr (Complex a) -> Ptr (Complex a) ->
+   Sign -> Flags -> IO (Plan a)
+
+type PlanDFT2d a =
+   C.CInt -> C.CInt ->
+   Ptr (Complex a) -> Ptr (Complex a) ->
+   Sign -> Flags -> IO (Plan a)
+
+type PlanDFT3d a =
+   C.CInt -> C.CInt -> C.CInt ->
+   Ptr (Complex a) -> Ptr (Complex a) ->
+   Sign -> Flags -> IO (Plan a)
+
+type PlanDFT a =
+   C.CInt -> Ptr C.CInt ->
+   Ptr (Complex a) -> Ptr (Complex a) ->
+   Sign -> Flags -> IO (Plan a)
+
+type PlanDFTr2c1d a =
+   C.CInt ->
+   Ptr a -> Ptr (Complex a) ->
+   Flags -> IO (Plan a)
+
+type PlanDFTr2c2d a =
+   C.CInt -> C.CInt ->
+   Ptr a -> Ptr (Complex a) ->
+   Flags -> IO (Plan a)
+
+type PlanDFTr2c3d a =
+   C.CInt -> C.CInt -> C.CInt ->
+   Ptr a -> Ptr (Complex a) ->
+   Flags -> IO (Plan a)
+
+type PlanDFTr2c a =
+   C.CInt -> Ptr C.CInt ->
+   Ptr a -> Ptr (Complex a) ->
+   Flags -> IO (Plan a)
+
+type PlanDFTc2r1d a =
+   C.CInt ->
+   Ptr (Complex a) -> Ptr a ->
+   Flags -> IO (Plan a)
+
+type PlanDFTc2r2d a =
+   C.CInt -> C.CInt ->
+   Ptr (Complex a) -> Ptr a ->
+   Flags -> IO (Plan a)
+
+type PlanDFTc2r3d a =
+   C.CInt -> C.CInt -> C.CInt ->
+   Ptr (Complex a) -> Ptr a ->
+   Flags -> IO (Plan a)
+
+type PlanDFTc2r a =
+   C.CInt -> Ptr C.CInt ->
+   Ptr (Complex a) -> Ptr a ->
+   Flags -> IO (Plan a)
+
+type PlanR2r1d a =
+   C.CInt ->
+   Ptr a -> Ptr a ->
+   Kind -> Flags -> IO (Plan a)
+
+type PlanR2r2d a =
+   C.CInt -> C.CInt ->
+   Ptr a -> Ptr a ->
+   Kind -> Kind -> Flags -> IO (Plan a)
+
+type PlanR2r3d a =
+   C.CInt -> C.CInt -> C.CInt ->
+   Ptr a -> Ptr a ->
+   Kind -> Kind -> Kind -> Flags -> IO (Plan a)
+
+type PlanR2r a =
+   C.CInt -> Ptr C.CInt ->
+   Ptr a -> Ptr a ->
+   Ptr Kind -> Flags -> IO (Plan a)
+
+type PlanManyDFT a =
+   C.CInt -> Ptr C.CInt -> C.CInt ->
+   Ptr (Complex a) -> Ptr C.CInt ->
+   C.CInt -> C.CInt ->
+   Ptr (Complex a) -> Ptr C.CInt ->
+   C.CInt -> C.CInt ->
+   Sign -> Flags -> IO (Plan a)
+
+type PlanManyDFTr2c a =
+   C.CInt -> Ptr C.CInt -> C.CInt ->
+   Ptr a -> Ptr C.CInt ->
+   C.CInt -> C.CInt ->
+   Ptr (Complex a) -> Ptr C.CInt ->
+   C.CInt -> C.CInt ->
+   Flags -> IO (Plan a)
+
+type PlanManyDFTc2r a =
+   C.CInt -> Ptr C.CInt -> C.CInt ->
+   Ptr (Complex a) -> Ptr C.CInt ->
+   C.CInt -> C.CInt ->
+   Ptr a -> Ptr C.CInt ->
+   C.CInt -> C.CInt ->
+   Flags -> IO (Plan a)
+
+type PlanManyR2r a =
+   C.CInt -> Ptr C.CInt -> C.CInt ->
+   Ptr a -> Ptr C.CInt ->
+   C.CInt -> C.CInt ->
+   Ptr a -> Ptr C.CInt ->
+   C.CInt -> C.CInt ->
+   Ptr Kind -> Flags -> IO (Plan a)
+
+type PlanGuruDFT a =
+   C.CInt -> Ptr IODim -> C.CInt -> Ptr IODim ->
+   Ptr (Complex a) -> Ptr (Complex a) -> Sign -> Flags -> IO (Plan a)
+
+type PlanGuruDFTr2c a =
+   C.CInt -> Ptr IODim -> C.CInt -> Ptr IODim ->
+   Ptr a -> Ptr (Complex a) -> Flags -> IO (Plan a)
+
+type PlanGuruDFTc2r a =
+   C.CInt -> Ptr IODim -> C.CInt -> Ptr IODim ->
+   Ptr (Complex a) -> Ptr a -> Flags -> IO (Plan a)
+
+type PlanGuruR2r a =
+   C.CInt -> Ptr IODim -> C.CInt -> Ptr IODim ->
+   Ptr a -> Ptr a -> Ptr Kind -> Flags -> IO (Plan a)
+
+type PlanGuruSplitDFT a =
+   C.CInt -> Ptr IODim -> C.CInt -> Ptr IODim ->
+   Ptr a -> Ptr a -> Ptr a -> Ptr a -> Flags -> IO (Plan a)
+
+type PlanGuruSplitDFTr2c a =
+   C.CInt -> Ptr IODim -> C.CInt -> Ptr IODim ->
+   Ptr a -> Ptr a -> Ptr a -> Flags -> IO (Plan a)
+
+type PlanGuruSplitDFTc2r a =
+   C.CInt -> Ptr IODim -> C.CInt -> Ptr IODim ->
+   Ptr a -> Ptr a -> Ptr a -> Flags -> IO (Plan a)
+
+type DestroyPlan a =
+   Plan a -> IO ()
+
+type Execute a =
+   Plan a -> IO ()
+
+type ExecuteDFT a =
+   Plan a -> Ptr (Complex a) -> Ptr (Complex a) -> IO ()
+
+type ExecuteDFTr2c a =
+   Plan a -> Ptr a -> Ptr (Complex a) -> IO ()
+
+type ExecuteDFTc2r a =
+   Plan a -> Ptr (Complex a) -> Ptr a -> IO ()
+
+type ExecuteR2r a =
+   Plan a -> Ptr a -> Ptr a -> IO ()
+
+type ExecuteSplitDFT a =
+   Plan a -> Ptr a -> Ptr a -> Ptr a -> Ptr a -> IO ()
+
+type ExecuteSplitDFTr2c a =
+   Plan a -> Ptr a -> Ptr a -> Ptr a -> IO ()
+
+type ExecuteSplitDFTc2r a =
+   Plan a -> Ptr a -> Ptr a -> Ptr a -> IO ()
+
+type Malloc a =
+   C.CSize -> IO (Ptr a)
+
+type Free a =
+   Ptr a -> IO ()
+
+type AllocReal a =
+   C.CSize -> IO (Ptr a)
+
+type AllocComplex a =
+   C.CSize -> IO (Ptr (Complex a))
+
+type FreeComplex a =
+   Ptr (Complex a) -> IO ()
diff --git a/src/Numeric/FFTW/FFI/Generic.hs b/src/Numeric/FFTW/FFI/Generic.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/FFTW/FFI/Generic.hs
@@ -0,0 +1,461 @@
+-- Do not edit! Automatically generated by fftw-generate.
+module Numeric.FFTW.FFI.Generic (
+   FFT.PlanDFT1d, planDFT1d,
+   FFT.PlanDFT2d, planDFT2d,
+   FFT.PlanDFT3d, planDFT3d,
+   FFT.PlanDFT, planDFT,
+   FFT.PlanDFTr2c1d, planDFTr2c1d,
+   FFT.PlanDFTr2c2d, planDFTr2c2d,
+   FFT.PlanDFTr2c3d, planDFTr2c3d,
+   FFT.PlanDFTr2c, planDFTr2c,
+   FFT.PlanDFTc2r1d, planDFTc2r1d,
+   FFT.PlanDFTc2r2d, planDFTc2r2d,
+   FFT.PlanDFTc2r3d, planDFTc2r3d,
+   FFT.PlanDFTc2r, planDFTc2r,
+   FFT.PlanR2r1d, planR2r1d,
+   FFT.PlanR2r2d, planR2r2d,
+   FFT.PlanR2r3d, planR2r3d,
+   FFT.PlanR2r, planR2r,
+   FFT.PlanManyDFT, planManyDFT,
+   FFT.PlanManyDFTr2c, planManyDFTr2c,
+   FFT.PlanManyDFTc2r, planManyDFTc2r,
+   FFT.PlanManyR2r, planManyR2r,
+   FFT.PlanGuruDFT, planGuruDFT,
+   FFT.PlanGuruDFTr2c, planGuruDFTr2c,
+   FFT.PlanGuruDFTc2r, planGuruDFTc2r,
+   FFT.PlanGuruR2r, planGuruR2r,
+   FFT.PlanGuruSplitDFT, planGuruSplitDFT,
+   FFT.PlanGuruSplitDFTr2c, planGuruSplitDFTr2c,
+   FFT.PlanGuruSplitDFTc2r, planGuruSplitDFTc2r,
+   FFT.DestroyPlan, destroyPlan,
+   FFT.Execute, execute,
+   FFT.ExecuteDFT, executeDFT,
+   FFT.ExecuteDFTr2c, executeDFTr2c,
+   FFT.ExecuteDFTc2r, executeDFTc2r,
+   FFT.ExecuteR2r, executeR2r,
+   FFT.ExecuteSplitDFT, executeSplitDFT,
+   FFT.ExecuteSplitDFTr2c, executeSplitDFTr2c,
+   FFT.ExecuteSplitDFTc2r, executeSplitDFTc2r,
+   FFT.Malloc, malloc,
+   FFT.Free, free,
+   FFT.AllocReal, allocReal,
+   FFT.AllocComplex, allocComplex,
+   FFT.FreeComplex, freeComplex,
+   ) where
+
+import qualified Numeric.FFTW.FFI.Double as FFTD
+import qualified Numeric.FFTW.FFI.Float  as FFTF
+import qualified Numeric.FFTW.FFI.Function as FFT
+
+import qualified Numeric.Netlib.Class as Class
+
+
+newtype PlanDFT1d a =
+   PlanDFT1d {runPlanDFT1d :: FFT.PlanDFT1d a}
+
+planDFT1d :: (Class.Real a) => FFT.PlanDFT1d a
+planDFT1d =
+   runPlanDFT1d $
+   Class.switchReal
+      (PlanDFT1d FFTF.planDFT1d)
+      (PlanDFT1d FFTD.planDFT1d)
+
+newtype PlanDFT2d a =
+   PlanDFT2d {runPlanDFT2d :: FFT.PlanDFT2d a}
+
+planDFT2d :: (Class.Real a) => FFT.PlanDFT2d a
+planDFT2d =
+   runPlanDFT2d $
+   Class.switchReal
+      (PlanDFT2d FFTF.planDFT2d)
+      (PlanDFT2d FFTD.planDFT2d)
+
+newtype PlanDFT3d a =
+   PlanDFT3d {runPlanDFT3d :: FFT.PlanDFT3d a}
+
+planDFT3d :: (Class.Real a) => FFT.PlanDFT3d a
+planDFT3d =
+   runPlanDFT3d $
+   Class.switchReal
+      (PlanDFT3d FFTF.planDFT3d)
+      (PlanDFT3d FFTD.planDFT3d)
+
+newtype PlanDFT a =
+   PlanDFT {runPlanDFT :: FFT.PlanDFT a}
+
+planDFT :: (Class.Real a) => FFT.PlanDFT a
+planDFT =
+   runPlanDFT $
+   Class.switchReal
+      (PlanDFT FFTF.planDFT)
+      (PlanDFT FFTD.planDFT)
+
+newtype PlanDFTr2c1d a =
+   PlanDFTr2c1d {runPlanDFTr2c1d :: FFT.PlanDFTr2c1d a}
+
+planDFTr2c1d :: (Class.Real a) => FFT.PlanDFTr2c1d a
+planDFTr2c1d =
+   runPlanDFTr2c1d $
+   Class.switchReal
+      (PlanDFTr2c1d FFTF.planDFTr2c1d)
+      (PlanDFTr2c1d FFTD.planDFTr2c1d)
+
+newtype PlanDFTr2c2d a =
+   PlanDFTr2c2d {runPlanDFTr2c2d :: FFT.PlanDFTr2c2d a}
+
+planDFTr2c2d :: (Class.Real a) => FFT.PlanDFTr2c2d a
+planDFTr2c2d =
+   runPlanDFTr2c2d $
+   Class.switchReal
+      (PlanDFTr2c2d FFTF.planDFTr2c2d)
+      (PlanDFTr2c2d FFTD.planDFTr2c2d)
+
+newtype PlanDFTr2c3d a =
+   PlanDFTr2c3d {runPlanDFTr2c3d :: FFT.PlanDFTr2c3d a}
+
+planDFTr2c3d :: (Class.Real a) => FFT.PlanDFTr2c3d a
+planDFTr2c3d =
+   runPlanDFTr2c3d $
+   Class.switchReal
+      (PlanDFTr2c3d FFTF.planDFTr2c3d)
+      (PlanDFTr2c3d FFTD.planDFTr2c3d)
+
+newtype PlanDFTr2c a =
+   PlanDFTr2c {runPlanDFTr2c :: FFT.PlanDFTr2c a}
+
+planDFTr2c :: (Class.Real a) => FFT.PlanDFTr2c a
+planDFTr2c =
+   runPlanDFTr2c $
+   Class.switchReal
+      (PlanDFTr2c FFTF.planDFTr2c)
+      (PlanDFTr2c FFTD.planDFTr2c)
+
+newtype PlanDFTc2r1d a =
+   PlanDFTc2r1d {runPlanDFTc2r1d :: FFT.PlanDFTc2r1d a}
+
+planDFTc2r1d :: (Class.Real a) => FFT.PlanDFTc2r1d a
+planDFTc2r1d =
+   runPlanDFTc2r1d $
+   Class.switchReal
+      (PlanDFTc2r1d FFTF.planDFTc2r1d)
+      (PlanDFTc2r1d FFTD.planDFTc2r1d)
+
+newtype PlanDFTc2r2d a =
+   PlanDFTc2r2d {runPlanDFTc2r2d :: FFT.PlanDFTc2r2d a}
+
+planDFTc2r2d :: (Class.Real a) => FFT.PlanDFTc2r2d a
+planDFTc2r2d =
+   runPlanDFTc2r2d $
+   Class.switchReal
+      (PlanDFTc2r2d FFTF.planDFTc2r2d)
+      (PlanDFTc2r2d FFTD.planDFTc2r2d)
+
+newtype PlanDFTc2r3d a =
+   PlanDFTc2r3d {runPlanDFTc2r3d :: FFT.PlanDFTc2r3d a}
+
+planDFTc2r3d :: (Class.Real a) => FFT.PlanDFTc2r3d a
+planDFTc2r3d =
+   runPlanDFTc2r3d $
+   Class.switchReal
+      (PlanDFTc2r3d FFTF.planDFTc2r3d)
+      (PlanDFTc2r3d FFTD.planDFTc2r3d)
+
+newtype PlanDFTc2r a =
+   PlanDFTc2r {runPlanDFTc2r :: FFT.PlanDFTc2r a}
+
+planDFTc2r :: (Class.Real a) => FFT.PlanDFTc2r a
+planDFTc2r =
+   runPlanDFTc2r $
+   Class.switchReal
+      (PlanDFTc2r FFTF.planDFTc2r)
+      (PlanDFTc2r FFTD.planDFTc2r)
+
+newtype PlanR2r1d a =
+   PlanR2r1d {runPlanR2r1d :: FFT.PlanR2r1d a}
+
+planR2r1d :: (Class.Real a) => FFT.PlanR2r1d a
+planR2r1d =
+   runPlanR2r1d $
+   Class.switchReal
+      (PlanR2r1d FFTF.planR2r1d)
+      (PlanR2r1d FFTD.planR2r1d)
+
+newtype PlanR2r2d a =
+   PlanR2r2d {runPlanR2r2d :: FFT.PlanR2r2d a}
+
+planR2r2d :: (Class.Real a) => FFT.PlanR2r2d a
+planR2r2d =
+   runPlanR2r2d $
+   Class.switchReal
+      (PlanR2r2d FFTF.planR2r2d)
+      (PlanR2r2d FFTD.planR2r2d)
+
+newtype PlanR2r3d a =
+   PlanR2r3d {runPlanR2r3d :: FFT.PlanR2r3d a}
+
+planR2r3d :: (Class.Real a) => FFT.PlanR2r3d a
+planR2r3d =
+   runPlanR2r3d $
+   Class.switchReal
+      (PlanR2r3d FFTF.planR2r3d)
+      (PlanR2r3d FFTD.planR2r3d)
+
+newtype PlanR2r a =
+   PlanR2r {runPlanR2r :: FFT.PlanR2r a}
+
+planR2r :: (Class.Real a) => FFT.PlanR2r a
+planR2r =
+   runPlanR2r $
+   Class.switchReal
+      (PlanR2r FFTF.planR2r)
+      (PlanR2r FFTD.planR2r)
+
+newtype PlanManyDFT a =
+   PlanManyDFT {runPlanManyDFT :: FFT.PlanManyDFT a}
+
+planManyDFT :: (Class.Real a) => FFT.PlanManyDFT a
+planManyDFT =
+   runPlanManyDFT $
+   Class.switchReal
+      (PlanManyDFT FFTF.planManyDFT)
+      (PlanManyDFT FFTD.planManyDFT)
+
+newtype PlanManyDFTr2c a =
+   PlanManyDFTr2c {runPlanManyDFTr2c :: FFT.PlanManyDFTr2c a}
+
+planManyDFTr2c :: (Class.Real a) => FFT.PlanManyDFTr2c a
+planManyDFTr2c =
+   runPlanManyDFTr2c $
+   Class.switchReal
+      (PlanManyDFTr2c FFTF.planManyDFTr2c)
+      (PlanManyDFTr2c FFTD.planManyDFTr2c)
+
+newtype PlanManyDFTc2r a =
+   PlanManyDFTc2r {runPlanManyDFTc2r :: FFT.PlanManyDFTc2r a}
+
+planManyDFTc2r :: (Class.Real a) => FFT.PlanManyDFTc2r a
+planManyDFTc2r =
+   runPlanManyDFTc2r $
+   Class.switchReal
+      (PlanManyDFTc2r FFTF.planManyDFTc2r)
+      (PlanManyDFTc2r FFTD.planManyDFTc2r)
+
+newtype PlanManyR2r a =
+   PlanManyR2r {runPlanManyR2r :: FFT.PlanManyR2r a}
+
+planManyR2r :: (Class.Real a) => FFT.PlanManyR2r a
+planManyR2r =
+   runPlanManyR2r $
+   Class.switchReal
+      (PlanManyR2r FFTF.planManyR2r)
+      (PlanManyR2r FFTD.planManyR2r)
+
+newtype PlanGuruDFT a =
+   PlanGuruDFT {runPlanGuruDFT :: FFT.PlanGuruDFT a}
+
+planGuruDFT :: (Class.Real a) => FFT.PlanGuruDFT a
+planGuruDFT =
+   runPlanGuruDFT $
+   Class.switchReal
+      (PlanGuruDFT FFTF.planGuruDFT)
+      (PlanGuruDFT FFTD.planGuruDFT)
+
+newtype PlanGuruDFTr2c a =
+   PlanGuruDFTr2c {runPlanGuruDFTr2c :: FFT.PlanGuruDFTr2c a}
+
+planGuruDFTr2c :: (Class.Real a) => FFT.PlanGuruDFTr2c a
+planGuruDFTr2c =
+   runPlanGuruDFTr2c $
+   Class.switchReal
+      (PlanGuruDFTr2c FFTF.planGuruDFTr2c)
+      (PlanGuruDFTr2c FFTD.planGuruDFTr2c)
+
+newtype PlanGuruDFTc2r a =
+   PlanGuruDFTc2r {runPlanGuruDFTc2r :: FFT.PlanGuruDFTc2r a}
+
+planGuruDFTc2r :: (Class.Real a) => FFT.PlanGuruDFTc2r a
+planGuruDFTc2r =
+   runPlanGuruDFTc2r $
+   Class.switchReal
+      (PlanGuruDFTc2r FFTF.planGuruDFTc2r)
+      (PlanGuruDFTc2r FFTD.planGuruDFTc2r)
+
+newtype PlanGuruR2r a =
+   PlanGuruR2r {runPlanGuruR2r :: FFT.PlanGuruR2r a}
+
+planGuruR2r :: (Class.Real a) => FFT.PlanGuruR2r a
+planGuruR2r =
+   runPlanGuruR2r $
+   Class.switchReal
+      (PlanGuruR2r FFTF.planGuruR2r)
+      (PlanGuruR2r FFTD.planGuruR2r)
+
+newtype PlanGuruSplitDFT a =
+   PlanGuruSplitDFT {runPlanGuruSplitDFT :: FFT.PlanGuruSplitDFT a}
+
+planGuruSplitDFT :: (Class.Real a) => FFT.PlanGuruSplitDFT a
+planGuruSplitDFT =
+   runPlanGuruSplitDFT $
+   Class.switchReal
+      (PlanGuruSplitDFT FFTF.planGuruSplitDFT)
+      (PlanGuruSplitDFT FFTD.planGuruSplitDFT)
+
+newtype PlanGuruSplitDFTr2c a =
+   PlanGuruSplitDFTr2c {runPlanGuruSplitDFTr2c :: FFT.PlanGuruSplitDFTr2c a}
+
+planGuruSplitDFTr2c :: (Class.Real a) => FFT.PlanGuruSplitDFTr2c a
+planGuruSplitDFTr2c =
+   runPlanGuruSplitDFTr2c $
+   Class.switchReal
+      (PlanGuruSplitDFTr2c FFTF.planGuruSplitDFTr2c)
+      (PlanGuruSplitDFTr2c FFTD.planGuruSplitDFTr2c)
+
+newtype PlanGuruSplitDFTc2r a =
+   PlanGuruSplitDFTc2r {runPlanGuruSplitDFTc2r :: FFT.PlanGuruSplitDFTc2r a}
+
+planGuruSplitDFTc2r :: (Class.Real a) => FFT.PlanGuruSplitDFTc2r a
+planGuruSplitDFTc2r =
+   runPlanGuruSplitDFTc2r $
+   Class.switchReal
+      (PlanGuruSplitDFTc2r FFTF.planGuruSplitDFTc2r)
+      (PlanGuruSplitDFTc2r FFTD.planGuruSplitDFTc2r)
+
+newtype DestroyPlan a =
+   DestroyPlan {runDestroyPlan :: FFT.DestroyPlan a}
+
+destroyPlan :: (Class.Real a) => FFT.DestroyPlan a
+destroyPlan =
+   runDestroyPlan $
+   Class.switchReal
+      (DestroyPlan FFTF.destroyPlan)
+      (DestroyPlan FFTD.destroyPlan)
+
+newtype Execute a =
+   Execute {runExecute :: FFT.Execute a}
+
+execute :: (Class.Real a) => FFT.Execute a
+execute =
+   runExecute $
+   Class.switchReal
+      (Execute FFTF.execute)
+      (Execute FFTD.execute)
+
+newtype ExecuteDFT a =
+   ExecuteDFT {runExecuteDFT :: FFT.ExecuteDFT a}
+
+executeDFT :: (Class.Real a) => FFT.ExecuteDFT a
+executeDFT =
+   runExecuteDFT $
+   Class.switchReal
+      (ExecuteDFT FFTF.executeDFT)
+      (ExecuteDFT FFTD.executeDFT)
+
+newtype ExecuteDFTr2c a =
+   ExecuteDFTr2c {runExecuteDFTr2c :: FFT.ExecuteDFTr2c a}
+
+executeDFTr2c :: (Class.Real a) => FFT.ExecuteDFTr2c a
+executeDFTr2c =
+   runExecuteDFTr2c $
+   Class.switchReal
+      (ExecuteDFTr2c FFTF.executeDFTr2c)
+      (ExecuteDFTr2c FFTD.executeDFTr2c)
+
+newtype ExecuteDFTc2r a =
+   ExecuteDFTc2r {runExecuteDFTc2r :: FFT.ExecuteDFTc2r a}
+
+executeDFTc2r :: (Class.Real a) => FFT.ExecuteDFTc2r a
+executeDFTc2r =
+   runExecuteDFTc2r $
+   Class.switchReal
+      (ExecuteDFTc2r FFTF.executeDFTc2r)
+      (ExecuteDFTc2r FFTD.executeDFTc2r)
+
+newtype ExecuteR2r a =
+   ExecuteR2r {runExecuteR2r :: FFT.ExecuteR2r a}
+
+executeR2r :: (Class.Real a) => FFT.ExecuteR2r a
+executeR2r =
+   runExecuteR2r $
+   Class.switchReal
+      (ExecuteR2r FFTF.executeR2r)
+      (ExecuteR2r FFTD.executeR2r)
+
+newtype ExecuteSplitDFT a =
+   ExecuteSplitDFT {runExecuteSplitDFT :: FFT.ExecuteSplitDFT a}
+
+executeSplitDFT :: (Class.Real a) => FFT.ExecuteSplitDFT a
+executeSplitDFT =
+   runExecuteSplitDFT $
+   Class.switchReal
+      (ExecuteSplitDFT FFTF.executeSplitDFT)
+      (ExecuteSplitDFT FFTD.executeSplitDFT)
+
+newtype ExecuteSplitDFTr2c a =
+   ExecuteSplitDFTr2c {runExecuteSplitDFTr2c :: FFT.ExecuteSplitDFTr2c a}
+
+executeSplitDFTr2c :: (Class.Real a) => FFT.ExecuteSplitDFTr2c a
+executeSplitDFTr2c =
+   runExecuteSplitDFTr2c $
+   Class.switchReal
+      (ExecuteSplitDFTr2c FFTF.executeSplitDFTr2c)
+      (ExecuteSplitDFTr2c FFTD.executeSplitDFTr2c)
+
+newtype ExecuteSplitDFTc2r a =
+   ExecuteSplitDFTc2r {runExecuteSplitDFTc2r :: FFT.ExecuteSplitDFTc2r a}
+
+executeSplitDFTc2r :: (Class.Real a) => FFT.ExecuteSplitDFTc2r a
+executeSplitDFTc2r =
+   runExecuteSplitDFTc2r $
+   Class.switchReal
+      (ExecuteSplitDFTc2r FFTF.executeSplitDFTc2r)
+      (ExecuteSplitDFTc2r FFTD.executeSplitDFTc2r)
+
+newtype Malloc a =
+   Malloc {runMalloc :: FFT.Malloc a}
+
+malloc :: (Class.Real a) => FFT.Malloc a
+malloc =
+   runMalloc $
+   Class.switchReal
+      (Malloc FFTF.malloc)
+      (Malloc FFTD.malloc)
+
+newtype Free a =
+   Free {runFree :: FFT.Free a}
+
+free :: (Class.Real a) => FFT.Free a
+free =
+   runFree $
+   Class.switchReal
+      (Free FFTF.free)
+      (Free FFTD.free)
+
+newtype AllocReal a =
+   AllocReal {runAllocReal :: FFT.AllocReal a}
+
+allocReal :: (Class.Real a) => FFT.AllocReal a
+allocReal =
+   runAllocReal $
+   Class.switchReal
+      (AllocReal FFTF.allocReal)
+      (AllocReal FFTD.allocReal)
+
+newtype AllocComplex a =
+   AllocComplex {runAllocComplex :: FFT.AllocComplex a}
+
+allocComplex :: (Class.Real a) => FFT.AllocComplex a
+allocComplex =
+   runAllocComplex $
+   Class.switchReal
+      (AllocComplex FFTF.allocComplex)
+      (AllocComplex FFTD.allocComplex)
+
+newtype FreeComplex a =
+   FreeComplex {runFreeComplex :: FFT.FreeComplex a}
+
+freeComplex :: (Class.Real a) => FFT.FreeComplex a
+freeComplex =
+   runFreeComplex $
+   Class.switchReal
+      (FreeComplex FFTF.freeComplex)
+      (FreeComplex FFTD.freeComplex)
diff --git a/src/Numeric/FFTW/FFI/Type.hsc b/src/Numeric/FFTW/FFI/Type.hsc
new file mode 100644
--- /dev/null
+++ b/src/Numeric/FFTW/FFI/Type.hsc
@@ -0,0 +1,97 @@
+module Numeric.FFTW.FFI.Type where
+
+import qualified Foreign.C.Types as C
+import Foreign.Ptr (Ptr)
+import Foreign.Storable
+          (Storable, sizeOf, alignment, peek, poke, peekByteOff, pokeByteOff)
+
+import qualified Data.EnumBitSet as EnumSet
+
+
+#include <Numeric/FFTW/FFI/Common.h>
+#include <fftw3.h>
+
+
+type Flags = EnumSet.T C.CUInt Flag
+{-
+Warning: Enum methods do not match flag positions.
+Thus we keep the Flag type private.
+-}
+data Flag =
+     Measure
+   | DestroyInput
+   | Unaligned
+   | ConserveMemory
+   | Exhaustive
+   | PreserveInput
+   | Patient
+   | Estimate
+   deriving (Eq, Ord, Enum)
+
+#{enum Flags, EnumSet.Cons
+   , measure        = FFTW_MEASURE
+   , destroyInput   = FFTW_DESTROY_INPUT
+   , unaligned      = FFTW_UNALIGNED
+   , conserveMemory = FFTW_CONSERVE_MEMORY
+   , exhaustive     = FFTW_EXHAUSTIVE
+   , preserveInput  = FFTW_PRESERVE_INPUT
+   , patient        = FFTW_PATIENT
+   , estimate       = FFTW_ESTIMATE
+   }
+
+
+newtype Sign = Sign C.CInt
+   deriving (Eq)
+
+#{enum Sign, Sign
+   , forward  = FFTW_FORWARD
+   , backward = FFTW_BACKWARD
+   }
+
+
+newtype Kind = Kind C.CInt
+   deriving (Eq)
+
+#{enum Kind, Kind
+   , r2hc    = FFTW_R2HC
+   , hc2r    = FFTW_HC2R
+   , dht     = FFTW_DHT
+   , redft00 = FFTW_REDFT00
+   , redft10 = FFTW_REDFT10
+   , redft01 = FFTW_REDFT01
+   , redft11 = FFTW_REDFT11
+   , rodft00 = FFTW_RODFT00
+   , rodft10 = FFTW_RODFT10
+   , rodft01 = FFTW_RODFT01
+   , rodft11 = FFTW_RODFT11
+   }
+
+
+{- |
+Corresponds to the @fftw_iodim@ structure.
+It completely describes the layout of each dimension,
+before and after the transform.
+-}
+data IODim = IODim {
+     ioDimN  :: Int -- ^ Logical size of dimension
+   , ioDimIS :: Int -- ^ Stride along dimension in input array
+   , ioDimOS :: Int -- ^ Stride along dimension in output array
+   }
+   deriving (Eq, Show)
+
+instance Storable IODim where
+   sizeOf _ = #{size fftw_iodim}
+   alignment _ = #{alignment fftw_iodim}
+   peek p = do
+      n'  <- #{peek fftw_iodim,  n} p
+      is' <- #{peek fftw_iodim, is} p
+      os' <- #{peek fftw_iodim, os} p
+      return (IODim n' is' os')
+   poke p (IODim n' is' os') = do
+      #{poke fftw_iodim,  n} p  n'
+      #{poke fftw_iodim, is} p is'
+      #{poke fftw_iodim, os} p os'
+
+
+type Plan a = Ptr (PlanObj a)
+data PlanObj a = PlanObj
diff --git a/tool/GenerateForeignImport.hs b/tool/GenerateForeignImport.hs
new file mode 100644
--- /dev/null
+++ b/tool/GenerateForeignImport.hs
@@ -0,0 +1,325 @@
+import System.Environment (getArgs)
+import Text.Printf (printf)
+
+import qualified Data.List as List
+import Data.Foldable (forM_)
+import Data.Char (toLower)
+
+
+data Safety = Unsafe | Safe deriving (Show)
+
+formatSafety :: Safety -> String
+formatSafety s =
+   case s of
+      Unsafe -> "unsafe"
+      Safe -> "safe"
+
+lowerInit :: String -> String
+lowerInit (c:cs) = toLower c : cs
+lowerInit "" = ""
+
+list :: [(String, Safety, String, [String])]
+list =
+   ("plan_dft_1d", Safe,
+    "PlanDFT1d",
+      "C.CInt ->" :
+      "Ptr (Complex a) -> Ptr (Complex a) ->" :
+      "Sign -> Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_dft_2d", Safe,
+    "PlanDFT2d",
+      "C.CInt -> C.CInt ->" :
+      "Ptr (Complex a) -> Ptr (Complex a) ->" :
+      "Sign -> Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_dft_3d", Safe,
+    "PlanDFT3d",
+      "C.CInt -> C.CInt -> C.CInt ->" :
+      "Ptr (Complex a) -> Ptr (Complex a) ->" :
+      "Sign -> Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_dft", Safe,
+    "PlanDFT",
+      "C.CInt -> Ptr C.CInt ->" :
+      "Ptr (Complex a) -> Ptr (Complex a) ->" :
+      "Sign -> Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_dft_r2c_1d", Safe,
+    "PlanDFTr2c1d",
+      "C.CInt ->" :
+      "Ptr a -> Ptr (Complex a) ->" :
+      "Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_dft_r2c_2d", Safe,
+    "PlanDFTr2c2d",
+      "C.CInt -> C.CInt ->" :
+      "Ptr a -> Ptr (Complex a) ->" :
+      "Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_dft_r2c_3d", Safe,
+    "PlanDFTr2c3d",
+      "C.CInt -> C.CInt -> C.CInt ->" :
+      "Ptr a -> Ptr (Complex a) ->" :
+      "Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_dft_r2c", Safe,
+    "PlanDFTr2c",
+      "C.CInt -> Ptr C.CInt ->" :
+      "Ptr a -> Ptr (Complex a) ->" :
+      "Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_dft_c2r_1d", Safe,
+    "PlanDFTc2r1d",
+      "C.CInt ->" :
+      "Ptr (Complex a) -> Ptr a ->" :
+      "Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_dft_c2r_2d", Safe,
+    "PlanDFTc2r2d",
+      "C.CInt -> C.CInt ->" :
+      "Ptr (Complex a) -> Ptr a ->" :
+      "Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_dft_c2r_3d", Safe,
+    "PlanDFTc2r3d",
+      "C.CInt -> C.CInt -> C.CInt ->" :
+      "Ptr (Complex a) -> Ptr a ->" :
+      "Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_dft_c2r", Safe,
+    "PlanDFTc2r",
+      "C.CInt -> Ptr C.CInt ->" :
+      "Ptr (Complex a) -> Ptr a ->" :
+      "Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_r2r_1d", Safe,
+    "PlanR2r1d",
+      "C.CInt ->" :
+      "Ptr a -> Ptr a ->" :
+      "Kind -> Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_r2r_2d", Safe,
+    "PlanR2r2d",
+      "C.CInt -> C.CInt ->" :
+      "Ptr a -> Ptr a ->" :
+      "Kind -> Kind -> Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_r2r_3d", Safe,
+    "PlanR2r3d",
+      "C.CInt -> C.CInt -> C.CInt ->" :
+      "Ptr a -> Ptr a ->" :
+      "Kind -> Kind -> Kind -> Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_r2r", Safe,
+    "PlanR2r",
+      "C.CInt -> Ptr C.CInt ->" :
+      "Ptr a -> Ptr a ->" :
+      "Ptr Kind -> Flags -> IO (Plan a)" :
+      []) :
+
+
+   ("plan_many_dft", Safe,
+    "PlanManyDFT",
+      "C.CInt -> Ptr C.CInt -> C.CInt ->" :
+      "Ptr (Complex a) -> Ptr C.CInt ->" :
+      "C.CInt -> C.CInt ->" :
+      "Ptr (Complex a) -> Ptr C.CInt ->" :
+      "C.CInt -> C.CInt ->" :
+      "Sign -> Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_many_dft_r2c", Safe,
+    "PlanManyDFTr2c",
+      "C.CInt -> Ptr C.CInt -> C.CInt ->" :
+      "Ptr a -> Ptr C.CInt ->" :
+      "C.CInt -> C.CInt ->" :
+      "Ptr (Complex a) -> Ptr C.CInt ->" :
+      "C.CInt -> C.CInt ->" :
+      "Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_many_dft_c2r", Safe,
+    "PlanManyDFTc2r",
+      "C.CInt -> Ptr C.CInt -> C.CInt ->" :
+      "Ptr (Complex a) -> Ptr C.CInt ->" :
+      "C.CInt -> C.CInt ->" :
+      "Ptr a -> Ptr C.CInt ->" :
+      "C.CInt -> C.CInt ->" :
+      "Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_many_r2r", Safe,
+    "PlanManyR2r",
+      "C.CInt -> Ptr C.CInt -> C.CInt ->" :
+      "Ptr a -> Ptr C.CInt ->" :
+      "C.CInt -> C.CInt ->" :
+      "Ptr a -> Ptr C.CInt ->" :
+      "C.CInt -> C.CInt ->" :
+      "Ptr Kind -> Flags -> IO (Plan a)" :
+      []) :
+
+
+   ("plan_guru_dft", Safe,
+    "PlanGuruDFT",
+      "C.CInt -> Ptr IODim -> C.CInt -> Ptr IODim ->" :
+      "Ptr (Complex a) -> Ptr (Complex a) -> Sign -> Flags -> IO (Plan a)" :
+      []) :
+   ("plan_guru_dft_r2c", Safe,
+    "PlanGuruDFTr2c",
+      "C.CInt -> Ptr IODim -> C.CInt -> Ptr IODim ->" :
+      "Ptr a -> Ptr (Complex a) -> Flags -> IO (Plan a)" :
+      []) :
+   ("plan_guru_dft_c2r", Safe,
+    "PlanGuruDFTc2r",
+      "C.CInt -> Ptr IODim -> C.CInt -> Ptr IODim ->" :
+      "Ptr (Complex a) -> Ptr a -> Flags -> IO (Plan a)" :
+      []) :
+   ("plan_guru_r2r", Safe,
+    "PlanGuruR2r",
+      "C.CInt -> Ptr IODim -> C.CInt -> Ptr IODim ->" :
+      "Ptr a -> Ptr a -> Ptr Kind -> Flags -> IO (Plan a)" :
+      []) :
+
+   ("plan_guru_split_dft", Safe,
+    "PlanGuruSplitDFT",
+      "C.CInt -> Ptr IODim -> C.CInt -> Ptr IODim ->" :
+      "Ptr a -> Ptr a -> Ptr a -> Ptr a -> Flags -> IO (Plan a)" :
+      []) :
+   ("plan_guru_split_dft_r2c", Safe,
+    "PlanGuruSplitDFTr2c",
+      "C.CInt -> Ptr IODim -> C.CInt -> Ptr IODim ->" :
+      "Ptr a -> Ptr a -> Ptr a -> Flags -> IO (Plan a)" :
+      []) :
+   ("plan_guru_split_dft_c2r", Safe,
+    "PlanGuruSplitDFTc2r",
+      "C.CInt -> Ptr IODim -> C.CInt -> Ptr IODim ->" :
+      "Ptr a -> Ptr a -> Ptr a -> Flags -> IO (Plan a)" :
+      []) :
+
+   ("destroy_plan", Safe,
+    "DestroyPlan",
+      "Plan a -> IO ()" :
+      []) :
+
+   ("execute", Safe,
+    "Execute",
+      "Plan a -> IO ()" :
+      []) :
+   ("execute_dft", Safe,
+    "ExecuteDFT",
+      "Plan a -> Ptr (Complex a) -> Ptr (Complex a) -> IO ()" :
+      []) :
+   ("execute_dft_r2c", Safe,
+    "ExecuteDFTr2c",
+      "Plan a -> Ptr a -> Ptr (Complex a) -> IO ()" :
+      []) :
+   ("execute_dft_c2r", Safe,
+    "ExecuteDFTc2r",
+      "Plan a -> Ptr (Complex a) -> Ptr a -> IO ()" :
+      []) :
+   ("execute_r2r", Safe,
+    "ExecuteR2r",
+      "Plan a -> Ptr a -> Ptr a -> IO ()" :
+      []) :
+   ("execute_split_dft", Safe,
+    "ExecuteSplitDFT",
+      "Plan a -> Ptr a -> Ptr a -> Ptr a -> Ptr a -> IO ()" :
+      []) :
+   ("execute_split_dft_r2c", Safe,
+    "ExecuteSplitDFTr2c",
+      "Plan a -> Ptr a -> Ptr a -> Ptr a -> IO ()" :
+      []) :
+   ("execute_split_dft_c2r", Safe,
+    "ExecuteSplitDFTc2r",
+      "Plan a -> Ptr a -> Ptr a -> Ptr a -> IO ()" :
+      []) :
+
+   ("malloc", Unsafe,
+    "Malloc",
+      "C.CSize -> IO (Ptr a)" :
+      []) :
+   ("free", Unsafe,
+    "Free",
+      "Ptr a -> IO ()" :
+      []) :
+
+   ("alloc_real", Unsafe,
+    "AllocReal",
+      "C.CSize -> IO (Ptr a)" :
+      []) :
+   ("alloc_complex", Unsafe,
+    "AllocComplex",
+      "C.CSize -> IO (Ptr (Complex a))" :
+      []) :
+   ("free", Unsafe,
+    "FreeComplex",
+      "Ptr (Complex a) -> IO ()" :
+      []) :
+
+   []
+
+
+-- cf. lapack-ffi-tools
+insertExportList :: [String] -> String -> String
+insertExportList exports modul =
+   (\(prefix,suffixes) ->
+      map fst prefix ++
+      case suffixes of
+         [] -> []
+         (_,suffix):_ ->
+            "(\n" ++ unlines (map (printf "   %s,") exports) ++
+            "   ) " ++ suffix) $
+   break (List.isPrefixOf "where" . snd) $
+   zip modul (List.tails modul)
+
+
+main :: IO ()
+main = do
+   args <- getArgs
+   case args of
+      [] ->
+         forM_ list $ \(_,_,funcName,typeExpr) -> do
+            printf "\ntype %s a =\n" funcName
+            mapM_ (printf "   %s\n") typeExpr
+
+      ["--generic", tmplPath] -> do
+         tmpl <- readFile tmplPath
+         let export (_,_,funcType,_) =
+               printf "FFT.%s, %s" funcType (lowerInit funcType)
+         putStr $ insertExportList (map export list) tmpl
+         forM_ list $ \(_,_,funcType,_) -> do
+            let funcName = lowerInit funcType
+            printf "\n"
+            printf "newtype %s a =\n" funcType
+            printf "   %s {run%s :: FFT.%s a}\n" funcType funcType funcType
+            printf "\n"
+            printf "%s :: (Class.Real a) => FFT.%s a\n" funcName funcType
+            printf "%s =\n" funcName
+            printf "   run%s $\n" funcType
+            printf "   Class.switchReal\n"
+            printf "      (%s FFTF.%s)\n" funcType funcName
+            printf "      (%s FFTD.%s)\n" funcType funcName
+
+      [floatName, cPrefix] ->
+         forM_ list $ \(cName,safety,funcName,_) -> do
+            printf "\nforeign import ccall %s \"fftw3.h %s_%s\"\n"
+               (formatSafety safety) cPrefix cName
+            printf "   %s :: FFT.%s %s\n"
+               (lowerInit funcName) funcName floatName
+
+      _ -> fail "wrong number of arguments"
