Well, we can reconstruct A34 by doing the inverse transform on FFTA34.
Obviously this makes the test somewhat circular - though the fact that a
sensible-looking A34 (with integer valued elements) exists is encouraging...
OK, then, here goes for hopefully final versions of script (fftw.ijs), test
script (testfftw.ijs) and updated lab (fftw.ijt)
David
fftw.ijs:
NB. built from project: ~Addons/math/fftw/fftw
NB. z definitions:
script_z_ '~system\main\dll.ijs'
coclass 'jfftw'
fftw_z_=: (_1 & fftwnd_jfftw_) :. (1 & fftwnd_jfftw_)
ifftw_z_=: (1 & fftwnd_jfftw_) :. (_1 & fftwnd_jfftw_)
NB. fftw utils
NB.
NB. cd 15!:0
NB. clean clean numbers near 0
NB. info cover for wdinfo
NB. matchclean if clean x-y is all 0
zzero=: 1j1-1j1
3 : 0''
if. IFUNIX do.
DLL=: 'libfftw3.so.3'
else.
DLL=: '"',~'"',jpath '~addons\math\fftw\libfftw3-3.dll'
end.
)
FFTW_FORWARD=: _1
FFTW_BACKWARD=: 1
FFTW_ESTIMATE=: 6 (33 b.) 1
FFTW_MEASURE=: 0
FFTW_VERSION=: 3.2
cd=: 15!:0
info=: wdinfo @ ('FFTW'&;)
matchclean=: 0: *./ . = clean @ , @: -
NB. =========================================================
NB.*clean v clean numbers to tolerance (default 1e_10)
NB. sets values less than tolerance to 0
clean=: (1e_10&$:) : (4 : 0)
if. L. y do.
x clean each y
else.
if. 16 ~: 3!:0 y do.
y * x <: |y
else.
j./"1 y* x <: | y=. +.y
end.
end.
)
NB. fftw
NB. =========================================================
NB.*createplan v create a plan
NB. y = shape ; in ; out ; direction; flag
NB.
NB. direction = FFTW_FORWARD | FFTW_BACKWARD
NB. flag = FFTW_ESTIMATE | FFTW_MEASURE
createplan=: 3 : 0
'shape in out dir flag'=. y
assert dir e. FFTW_FORWARD,FFTW_BACKWARD
assert flag e. FFTW_ESTIMATE, FFTW_MEASURE
shape=. ,shape
cmd=. DLL,' fftw_plan_dft + x i *i *j *j i i'
0 pick cmd cd (#shape);shape;in;out;dir;flag
)
NB. =========================================================
NB.*destroyplan v destroy a plan
destroyplan=: 3 : 0
cmd=. DLL,' fftw_destroy_plan + n x'
1 [ cmd cd y
)
NB. =========================================================
NB.*fftwnd d n-dimensional FFT
NB. x = _1 forward
NB. 1 backward
NB. y = data
fftwnd=: 4 : 0
shp=. $y
if. 0 e. shp do. y return. end.
in=. zzero + , |: y
out=. in * 0
assert x e. _1 1
dir=. x
plan=. createplan shp;in;out;dir;FFTW_ESTIMATE
fftwexecute plan
destroyplan plan
res=. |: (|.shp) $ out
if. dir=1 do. res % */shp end.
)
NB. =========================================================
NB.*fftwexecute d one call to n-dimensional FFT
NB. y = plan
fftwexecute=: 3 : 0
cmd=. DLL,' fftw_execute + n x'
1 [ cmd cd y
)
testfftw.ijs
NB. test fftw system
NB.
NB. load this file with 0!:2
NB.
NB. 0!:2 <'\jx\addon\fftw\fftw\testfftw.ijs'
load '~addons\math\fftw\fftw.ijs'
clean=: 1e_10&$: : (4 : 0)
if. (3!:0 y) e. 16 16384 do.
j./"1 y* x <: | y=. +.y
else.
y * x <: |y
end.
)
dfft=: 3 : '+/ y * ^ (#y) %~ (- o. 0j2 ) * */~ i.#y'
matchclean=: 0: *./ . = clean @ , @: -
round=: [ * [: <. 0.5"_ + %~
A34=: ". ;._2 (0 : 0)
0 1 1j7 2j10
1 0j6 4j1 5j8
8j14 3j12 5j21 9j20
)
FFTA34=: ". ;._2 (0 : 0)
39j99 _10j_10 10.3661j18.8301 9.3205j_6.6795
_8j6 _33.0788j_17.2417 _13.9282j3.0526 8.634j10.1698
_1j13 _25.3205j_41.3205 24.0789j_39.7584 _0.0718j_35.0526
)
NB. =========================================================
NB. test dat = ifftw fftw dat
f=: matchclean if...@fftw
f 3
f i.8
f i.4096
f i.2 3 4
f ?.(6?.10)$100
NB. =========================================================
NB. test against direct calculation
f=: dfft matchclean fftw
f 3
f i.8
f i.132
NB. =========================================================
NB. known examples:
a=: 2 0 1 0 0 0 1 0
b=: 4 2 0 2 4 2 0 2
a matchclean ifftw b
b matchclean fftw a
FFTA34 matchclean 1e_4 round fftw A34
NB. =========================================================
NB. createplan, performance 'measure'
NB. In this case, must initialize input array _after_ creating plan.
NB. Note use of in-place modification to do this, and to re-use the plan
with
NB. new input.
in=: 12 $ 1j1 NB. Make sure elements are complex
values.
out=: in * 0
P=: createplan_jfftw_ 3 4;in;out;_1;0
in=: (,|:A34) a: } in
fftwexecute_jfftw_ P
FFTA34 matchclean 1e_4 round |: (4 3) $ out
in=: (2 * in) a: } in
fftwexecute_jfftw_ P
FFTA34 matchclean 1e_4 round -: |: (4 3) $ out
destroyplan_jfftw_ P
NB. createplan, performance 'estimate'
NB. Again note use of in-place modification when re-using plan with new
input.
in=: , |: A34
out=: in * 0
P=: createplan_jfftw_ 3 4;in;out;_1;64
fftwexecute_jfftw_ P
FFTA34 matchclean 1e_4 round |: (4 3) $ out
in=: (2 * in) a: } in
fftwexecute_jfftw_ P
FFTA34 matchclean 1e_4 round -: |: (4 3) $ out
destroyplan_jfftw_ P
fftw.ijt:
LABTITLE=: 'Fast Fourier Transform'
LABWINDOWED=: 0
LABFOCUS=: 0
NB. =========================================================
Lab Section FFTW
Fast Fourier Transform routines in J are based on the FFTW library, i.e. the
Fastest Fourier Transform in the West.
FFTW is a comprehensive collection of fast C routines for computing the
discrete Fourier transform (DFT) in one or more dimensions, of both real and
complex data, and of arbitrary input size.
FFTW was developed at MIT by Matteo Frigo and Steven G. Johnson, and a full
description is available at the FFTW home page:
http://theory.lcs.mit.edu/~fftw/
FFTW is licensed under the GNU General Public License, see
addons/math/fftw/gpl.htm.
)
NB. =========================================================
Lab Section Source Files
The FFTW routines are packaged in file libfftw3-3.dll, which includes the
complete set of complex number routines in FFTW.
These routines are accessible to J through the J DLL call mechanism as
documented in User Manual chapter "Dlls and Memory Management".
)
NB. =========================================================
Lab Section
The scripts and other files for FFTW are in subdirectory fftw/math
of the addons directory, i.e.
)
jpath '~addons/math/fftw'
NB. =========================================================
Lab Section Loading FFTW
Load the fftw.ijs script to access FFTW.
The main definitions for FFTW are read into locale jfftw.
Two verbs are defined in the z locale:
fftw forward FFT
ifftw backward FFT
)
load 'math/fftw'
NB. =========================================================
Lab Section Examples
Here is a simple example:
)
fftw i.8
NB. =========================================================
Lab Section
This example is easily verified by direct computation in J.
The discrete FFT for vector f is given by:
N-1
F(k) = sigma f(n) exp ((- j 2 pi n k)/N) k = 0 ... N-1
n=0
The verb dfft defined below implements the above expression, and matches the
result of fftw. However, it is very inefficient for large arguments.
Note that we remove small rounding errors by using the verb clean from the
numeric script.
)
dfft=: 3 : '+/ y * ^ (#y) %~ (- o. 0j2 ) * */~ i.#y'
require 'numeric'
clean (dfft - fftw) i.8
NB. =========================================================
Lab Section
The inverse FFT is given by:
ifftw
or equivalently:
fftw inverse
Note that the inverse is normalized, so that the inverse FFT returns the
original data.
)
ifftw fftw i.8
fftw inverse fftw i.8
NB. =========================================================
Lab Section
Doing a FFT followed by an inverse FFT returns the original data, so that
the following expression is everywhere zero:
dat - ifftw fftw dat
In practice, there may be small rounding errors. Again, we use clean to
remove these.
)
A=: ?.~ 8
A - ifftw fftw A
clean A - ifftw fftw A
NB. =========================================================
Lab Section
In general, the arguments to fftw and ifftw are complex, multidimensional
arrays.
The next section computes the FFT on a random complex, 6-dimensional array
of shape 3 4 5 6 7 8. This may take a few seconds to run.
)
NB. =========================================================
Lab Section
)
A=: j./ ?. 1 + i. 2 3 4 5 6 7 8
$A
$B=: fftw A
$C=: ifftw B
+/ , clean A - C NB. A matches C
NB. =========================================================
Lab Section Other Facilities
The verbs fftw and ifftw should cover practically all uses of FFTW.
However, there are two other facilities that are designed to optimize
repeated uses of the FFTW library on arguments of the same shape, which are
supported by the utilities in the jfftw locale:
saved plans
performance measures
)
NB. =========================================================
Lab Section
When using the underlying facilities directly, take care to ensure the
arguments given are correct. Calling DLL procedures incorrectly can crash
your system or corrupt memory.
)
NB. =========================================================
Lab Section Saved Plans
The verbs fftw and ifftw dynamically create and destroy plans. If you are
calling an FFT on same sized arrays repeatedly, you can create and reuse a
plan, destroying it when no longer required.
In the following example, a plan is created for a 2 3 4 array, and FFT is
called twice using it:
)
shape=: 2 3 4
data=: j./? 1+ i.2, shape NB. random data
NB. get data in right shape for library call and allocate
NB. space for output.
in=: (,|:data)
out=: in * 0
[P=: createplan_jfftw_ shape;in;out;_1;64 NB. create plan
NB. execute plan. Result goes to out, which we must reshape
fftwexecute_jfftw_ P
|: (|.shape) $ out
data=: j./? 1+ i.2, shape NB. new random data
in=: (,|:data) a: } in NB. in-place update of input
data
fftwexecute_jfftw_ P NB. reuse existing plan
|: (|.shape) $ out
destroyplan_jfftw_ P NB. destroy plan
NB. =========================================================
Lab Section Performance Measures
The final argument to the verb createplan is a flag, 0=MEASURE or
64=ESTIMATE, where ESTIMATE is the default.
Plans created with the MEASURE flag are optimized for a given array size. It
takes much longer to create such plans than with ESTIMATE, and so you would
do this only when a large number of FFTs are to be calculated for the same
array shape.
When creating plans with the ESTIMATE flag you may set up the input either
before or after creating the plan. But when creating plans with the MEASURE
flag, you must set up the input after creating the plan.
The next section creates a plan with a performance measure. It will take a
little longer to run, most of the time being spent creating the plan.
)
NB. =========================================================
Lab Section
)
shape=: 2 3 4
in=: (*/ shape) $ 1j1 NB. input must hold complex
values
out=: in * 0
[P=: createplan_jfftw_ shape;in;out;_1;0 NB. create plan
NB. populate input after creating plan.
data=: j./? 1+ i.2, shape
in=: (,|:data) a: } in
fftwexecute_jfftw_ P NB. execute plan
|: (|.shape) $ out NB. result goes to out
destroyplan_jfftw_ P NB. destroy plan
"bill lam" <[email protected]> wrote in message
news:[email protected]...
> lun, 22 Mar 2010, David Hotham skribis:
>> Hm. fftw A34 is still not equal to FFTA34.
>>
>> On win32 I see the same failure with the old script, though (and the new
>> script gives the same answer for fftw A34 as the old script did).
>>
>> Have you tried this yourself? Does the test pass for you (with either
>> old
>> or new script)?
>
> No, I didn't. I use 64-bit linux. It may employ some other methods to
> get the actual A34, such as run on some ancient J or ifftw2 or from
> matlab.
>
> --
> regards,
> ====================================================
> GPG key 1024D/4434BAB3 2008-08-24
> gpg --keyserver subkeys.pgp.net --recv-keys 4434BAB3
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
>
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm