Skip to content

Commit b923873

Browse files
committed
incorporate template_*.c into .pd
1 parent 6f8987f commit b923873

File tree

5 files changed

+59
-85
lines changed

5 files changed

+59
-85
lines changed

MANIFEST

-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,4 @@ MANIFEST This list of files
66
README.pod
77
t/fftw.t
88
t/threads.t
9-
template_complex.c
10-
template_real.c
119
TODO

Makefile.PL

-2
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ push @{$descriptor{LIBS} }, $libs;
5555
$descriptor{INC} = '' unless defined $descriptor{INC};
5656
$descriptor{INC} .= " $cflags";
5757

58-
$descriptor{depend} = { 'FFTW3.pm' => join(' ', qw(template_complex.c template_real.c)) };
59-
6058
$descriptor{PREREQ_PM} = {
6159
'PDL' => '2.049', # as_native
6260
};

fftw3.pd

+59-12
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,67 @@ EOF
3131

3232
pp_addhdr( '
3333
#include <fftw3.h>
34+
35+
/* the Linux kernel does something similar to assert at compile time */
36+
#define static_assert_fftw(x) (void)( sizeof( int[ 1 - 2* !(x) ]) )
3437
' );
3538

3639

3740
# I want to be able to say $X = fft1($x); rank is required. 'fft()' is ambiguous
3841
# about whether threading is desired or if a large fft is desired. Old PDL::FFTW
3942
# did one thing, matlab does another, so I do not include this function at all
4043

44+
my $TEMPLATE_REAL = <<'EOF';
45+
// This is the template used by PP to generate the FFTW routines.
46+
47+
// This is passed into pp_def() in the 'Code' key. Before this file is passed to
48+
// pp_def, the following strings are replaced:
49+
//
50+
// INVERSE If this is a c2r transform rather than r2c
51+
// RANK The rank of this transform
52+
53+
{
54+
// make sure the PDL data type I'm using matches the FFTW data type
55+
static_assert_fftw( sizeof($GENERIC())*2 == sizeof($TFD(fftwf_,fftw_)complex) );
56+
57+
$TFD(fftwf_,fftw_)plan plan = INT2PTR( $TFD(fftwf_,fftw_)plan, $COMP(plan));
4158

59+
if( !INVERSE )
60+
$TFD(fftwf_,fftw_)execute_dft_r2c( plan,
61+
($TFD(float,double)*)$P(real),
62+
($TFD(fftwf_,fftw_)complex*)$P(complexv) );
63+
else
64+
{
65+
// FFTW inverse real transforms clobber their input. I thus make a new
66+
// buffer and transform from there
67+
unsigned long nelem = 1;
68+
for( int i=0; i<=RANK; i++ )
69+
nelem *= $PDL(complexv)->dims[i];
70+
unsigned long elem_scale = sizeof($GENERIC()) / sizeof( $TFD(float,double) ); /* native complex */
71+
/* explicit C types here means when changed to $TGC will still be right */
72+
$TFD(float,double)* input_copy = $TFD(fftwf_,fftw_)alloc_real( nelem * elem_scale );
73+
memcpy( input_copy, $P(complexv), sizeof($GENERIC()) * nelem );
74+
75+
$TFD(fftwf_,fftw_)execute_dft_c2r( plan,
76+
($TFD(fftwf_,fftw_)complex*)input_copy,
77+
($TFD(float,double)*)$P(real) );
78+
79+
$TFD(fftwf_,fftw_)free( input_copy );
80+
}
81+
}
82+
EOF
83+
my $TEMPLATE_COMPLEX = <<'EOF';
84+
// This is the template used by PP to generate the FFTW routines.
85+
{
86+
// make sure the PDL data type I'm using matches the FFTW data type
87+
static_assert_fftw( sizeof($GENERIC())*2 == sizeof($TFD(fftwf_,fftw_)complex) );
4288

89+
$TFD(fftwf_,fftw_)plan plan = INT2PTR( $TFD(fftwf_,fftw_)plan, $COMP(plan));
90+
$TFD(fftwf_,fftw_)execute_dft( plan,
91+
($TFD(fftwf_,fftw_)complex*)$P(in),
92+
($TFD(fftwf_,fftw_)complex*)$P(out) );
93+
}
94+
EOF
4395

4496
# I define up to rank-10 FFTs. This is annoyingly arbitrary, but hopefully
4597
# should be sufficient
@@ -653,7 +705,6 @@ pp_add_exported( map "${_}fftn", '','i','r','ir' );
653705

654706
pp_done();
655707

656-
657708
sub generateDefinitions
658709
{
659710
my $rank = shift;
@@ -676,7 +727,7 @@ sub generateDefinitions
676727
unshift @dims, 'n0=2';
677728
my $dims_string = join(',', @dims);
678729
$pp_def{Pars} = "in($dims_string); [o]out($dims_string);";
679-
$pp_def{Code} = slurp('template_complex.c');
730+
$pp_def{Code} = $TEMPLATE_COMPLEX;
680731
pp_def( "__fft$rank", %pp_def );
681732

682733
##################################################################################
@@ -687,7 +738,7 @@ sub generateDefinitions
687738
$dims_complex[1] = 'nhalf'; # first complex dim is real->dim(0)/2+1
688739
my $dims_real_string = join(',', @dims_real);
689740
my $dims_complex_string = join(',', @dims_complex);
690-
my $code_real = slurp('template_real.c');
741+
my $code_real = $TEMPLATE_REAL;
691742
$code_real =~ s/RANK/$rank/ge;
692743
my $code_real_forward = $code_real;
693744
my $code_real_backward = $code_real;
@@ -730,7 +781,7 @@ EOF
730781
$dims_string = join(',', @dims);
731782
delete $pp_def{RedoDimsCode};
732783
$pp_def{Pars} = "in($dims_string); [o]out($dims_string);";
733-
$pp_def{Code} = slurp('template_complex.c');
784+
$pp_def{Code} = $TEMPLATE_COMPLEX;
734785
$pp_def{Code} =~ s/TFD/TGC/g;
735786
$pp_def{Code} =~ s/\*2//g; # the sizeof-doubling
736787
$pp_def{GenericTypes} = [qw(G C)];
@@ -743,7 +794,7 @@ EOF
743794
$dims_complex[0] = 'nhalf'; # first complex dim is real->dim(0)/2+1
744795
$dims_real_string = join(',', @dims_real);
745796
$dims_complex_string = join(',', @dims_complex);
746-
$code_real = slurp('template_real.c');
797+
$code_real = $TEMPLATE_REAL;
747798
$code_real =~ s/RANK/$rank-1/ge;
748799
$code_real_forward = $code_real;
749800
$code_real_backward = $code_real;
@@ -773,13 +824,9 @@ EOF
773824
pp_def( "__irNfft$rank", %pp_def );
774825
}
775826

776-
sub slurp
777-
{
827+
sub slurp {
778828
my $filename = shift;
779-
open FD, '<', $filename or die "Couldn't open '$filename' for rading";
780-
829+
open my $fh, '<', $filename or die "open '$filename' for reading: $!";
781830
local $/ = undef;
782-
my $contents = <FD>;
783-
close FD;
784-
return qq{\n#line 0 "$filename"\n\n} . $contents;
831+
return qq{\n#line 0 "$filename"\n\n} . <$fh>;
785832
}

template_complex.c

-22
This file was deleted.

template_real.c

-47
This file was deleted.

0 commit comments

Comments
 (0)