--- /dev/null
+! Copyright (c) 2014 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license.
+
+USING: alien alien.c-types alien.destructors alien.libraries
+alien.libraries.finder alien.syntax kernel ;
+
+IN: fftw.ffi
+
+LIBRARY: fftw3
+
+<< "fftw3" dup find-library cdecl add-library >>
+
+TYPEDEF: double[2] fftw_complex
+
+TYPEDEF: void* fftw_plan
+
+CONSTANT: FFTW_FORWARD -1
+CONSTANT: FFTW_BACKWARD 1
+
+CONSTANT: FFTW_MEASURE 0
+CONSTANT: FFTW_DESTROY_INPUT 1
+CONSTANT: FFTW_UNALIGNED 2
+CONSTANT: FFTW_CONSERVE_MEMORY 4
+CONSTANT: FFTW_EXHAUSTIVE 8
+CONSTANT: FFTW_PRESERVE_INPUT 16
+CONSTANT: FFTW_PATIENT 32
+CONSTANT: FFTW_ESTIMATE 64
+
+FUNCTION: void* fftw_malloc ( size_t n ) ;
+
+FUNCTION: fftw_plan fftw_plan_dft_1d ( int n, void* in, void* out, int sign, int flags ) ;
+
+FUNCTION: void fftw_destroy_plan ( fftw_plan ) ;
+
+FUNCTION: void fftw_execute ( fftw_plan ) ;
+
+FUNCTION: void fftw_free ( void* ) ;
+
+DESTRUCTOR: fftw_free
--- /dev/null
+! Copyright (c) 2014 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license.
+
+USING: alien.c-types destructors fftw.ffi fry kernel locals math
+math.functions math.vectors sequences sequences.private
+specialized-arrays ;
+SPECIALIZED-ARRAY: double
+SPECIALIZED-ARRAY: fftw_complex
+
+IN: fftw
+
+<PRIVATE
+
+: <fftw-array> ( length -- array )
+ [ fftw_complex heap-size * fftw_malloc &fftw_free ] keep
+ fftw_complex-array boa ;
+
+: >fftw-array ( seq -- array )
+ [ length <fftw-array> ] keep over '[
+ [ >rect 0 1 ] [ _ nth ] bi*
+ [ set-nth-unsafe ] curry bi-curry@ bi*
+ ] each-index ;
+
+: fftw-array> ( array -- seq )
+ [ first2 rect> ] { } map-as ;
+
+:: (fft1d) ( seq sign -- seq' )
+ seq length :> n
+ [
+ n
+ seq >fftw-array
+ n <fftw-array> [
+ sign FFTW_ESTIMATE fftw_plan_dft_1d
+ [ fftw_execute ] [ fftw_destroy_plan ] bi
+ ] keep fftw-array>
+ ] with-destructors ;
+
+PRIVATE>
+
+: fft1d ( seq -- seq' ) FFTW_FORWARD (fft1d) ;
+
+: ifft1d ( seq -- seq' ) FFTW_BACKWARD (fft1d) ;
+
+: correlate1d ( x y -- z )
+ [ fft1d ] [ reverse fft1d ] bi* v* ifft1d ;