1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
use strict;
use PDL;
use PDL::FFT;
use Test::More;
eval "use PDL::FFTW;";
my $loaded = ($@ ? 0 : 1);
# this value is add-hoc and adjusted each time we find a problem with a
# given OS or library version of FFTW...
#
# We use the PDL::Core::approx() routine for comparing piddles
#
use constant ABSDIFF => 1.2e-4;
if ($loaded) {
plan tests => 9;
} else {
plan skip_all => "PDL::FFTW not available";
}
# get the type (double or float) used by the FFTW library and module
# The eval() is to avoid warning messages from Perl
#
my $datatype = eval('$PDL::FFTW::COMPILED_TYPE');
my $n = 30;
my $m = 40;
my ( $ir, $ii, $i, $fi, $fir, $fii, $ffi );
$ir = zeroes($n,$m)->$datatype();
$ii = zeroes($n,$m)->$datatype();
$ir = random $ir;
$ii = random $ii;
$i = cat $ir,$ii;
$i = $i->mv(2,0);
$fi = ifftw $i;
$fir = $ir->copy;
$fii = $ii->copy;
fftnd $fir,$fii;
$ffi = cat $fir,$fii;
$ffi = $ffi->mv(2,0);
my ( $t, $orig, $i2, $sffi );
$t = ($ffi-$fi)*($ffi-$fi);
# print diff fftnd and ifftw: ",sqrt($t->sum),"\n";
ok(approx(sqrt($t->sum),pdl(0),ABSDIFF),
"fftnd() and ifftw()");
$orig = fftw $fi;
$orig /= $n*$m;
$t = ($orig-$i)*($orig-$i);
# print "diff ifftw fftw and orig: ",sqrt($t->sum),"\n";
ok(approx(sqrt($t->sum),pdl(0),ABSDIFF),
"ifftw() fftw() and original");
# Inplace FFT
$i2 = $i->copy;
infftw($i2);
$t = ($i2-$ffi)*($i2-$ffi);
# print "diff fftnd and infftw: ",sqrt($t->sum),"\n";
ok(approx(sqrt($t->sum),pdl(0),ABSDIFF),
"fftnd and infftw");
$i2 = nfftw $i2;
$i2 /= $n*$m;
$t = ($i-$i2)*($i-$i2);
# print "diff infftw nfftw and orig: ",sqrt($t->sum),"\n";
ok(approx(sqrt($t->sum),pdl(0),ABSDIFF),
"infftw nfftw and original");
$ir = zeroes($n,$m)->$datatype();
$ii = zeroes($n,$m)->$datatype();
$ir = random $ir;
$fir = $ir->copy;
$fii = $ii->copy;
ifftnd $fir,$fii;
$ffi = cat $fir,$fii;
$ffi = $ffi->mv(2,0);
$ffi *= $n*$m;
$sffi = $ffi->mslice('X',[0,$n/2],'X');
$fi = rfftw $ir;
$t = ($sffi-$fi)*($sffi-$fi);
# print "diff rfftw and infft: ",sqrt($t->sum),"\n";
ok(approx(sqrt($t->sum),pdl(0),ABSDIFF),
"rfftw() and infft()");
$orig = irfftw $fi;
$orig /= $n*$m;
$t = ($orig-$ir)*($orig-$ir);
# print "diff ifftw fftw and orig: ",sqrt($t->sum),"\n";
ok(approx(sqrt($t->sum),pdl(0),ABSDIFF),
"ifftw() fftw() and original");
my ( $rin, $srin, $tmp );
$rin = zeroes(2*(int($n/2)+1),$m)->$datatype();
$tmp = $rin->mslice([0,$n-1],'X');
$tmp .= $ir;
$srin = $rin->copy;
$rin = nrfftw $rin;
$t = ($sffi-$rin)*($sffi-$rin);
# print "diff nrfftw and infft: ",sqrt($t->sum),"\n";
ok(approx(sqrt($t->sum),pdl(0),ABSDIFF),
"nrfftw() and infft()");
$rin = inrfftw $rin;
$rin /= $n*$m;
$rin = $rin->mslice([0,$n-1],'X');
$srin = $srin->mslice([0,$n-1],'X');
$t = ($srin-$rin)*($srin-$rin);
# print "diff inrfftw nrfftw and orig: ",sqrt($t->sum),"\n";
ok(approx(sqrt($t->sum),pdl(0),ABSDIFF),
"inrfftw() nrfftw() and original");
# do the inplace routines work with slices?
my $a = ones(2,4)->$datatype();
my $fa = fftw $a;
nfftw $a->slice('');
ok(approx($fa,$a,ABSDIFF)->all,
"inplace routine (nfftw) works with slices");
#print "$a\n$fa\n";
|