fixed scaling for short real

moved fft.py from ./ to sample_code
This commit is contained in:
Mark Borgerding 2003-12-14 05:13:11 +00:00
parent 559c14b49b
commit 573536f48f
14 changed files with 96 additions and 244 deletions

View File

@ -95,5 +95,5 @@ void kf_work(
/* a debugging function */
static void pcpx( kiss_fft_cpx * c)
{
fprintf(stderr,"%g + %gi\n",c->r,c->i);
fprintf(stderr,"%g + %gi\n",(double)(c->r),(double)(c->i) );
}

View File

@ -80,6 +80,7 @@ void kiss_fftr(const void * cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *fr
freqdata[0].r = st->tmpbuf[0].r + st->tmpbuf[0].i;
freqdata[0].i = 0;
C_FIXDIV(freqdata[0],2);
for (k=1;k <= N/2 ; ++k ) {
kiss_fft_cpx fpnk,fpk,f1k,f2k,tw;
@ -87,22 +88,23 @@ void kiss_fftr(const void * cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *fr
fpk = st->tmpbuf[k];
fpnk.r = st->tmpbuf[N-k].r;
fpnk.i = -st->tmpbuf[N-k].i;
C_FIXDIV(fpk,2);
C_FIXDIV(fpnk,2);
C_ADD( f1k, fpk , fpnk );
C_SUB( f2k, fpk , fpnk );
C_MUL( tw , f2k , st->super_twiddles[k]);
C_ADD( freqdata[k] , f1k ,tw);
freqdata[k].r /= 2;
freqdata[k].i /= 2;
freqdata[k].r = (f1k.r + tw.r) / 2;
freqdata[k].i = (f1k.i + tw.i) / 2;
freqdata[N-k].r = f1k.r - tw.r;
freqdata[N-k].i = - (f1k.i - tw.i);
freqdata[N-k].r /= 2;
freqdata[N-k].i /= 2;
freqdata[N-k].r = (f1k.r - tw.r)/2;
freqdata[N-k].i = - (f1k.i - tw.i)/2;
}
freqdata[N].r = st->tmpbuf[0].r - st->tmpbuf[0].i;
freqdata[N].i = 0;
C_FIXDIV(freqdata[N],2);
}
void kiss_fftri(const void * cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata)
@ -120,6 +122,7 @@ void kiss_fftri(const void * cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *t
st->tmpbuf[0].r = freqdata[0].r + freqdata[N].r;
st->tmpbuf[0].i = freqdata[0].r - freqdata[N].r;
for (k = 1; k <= N / 2; ++k) {
kiss_fft_cpx fk, fnkc, fek, fok, tmpbuf;
fk = freqdata[k];

View File

@ -10,58 +10,61 @@ ifeq "$(DATATYPE)" ""
DATATYPE=float
endif
UTIL=fftutil_$(DATATYPE)
TESTREAL=tr_$(DATATYPE)
BENCHKISS=bm_kiss_$(DATATYPE)
BENCHFFTW=bm_fftw_$(DATATYPE)
all: $(UTIL) $(BENCHKISS) $(TESTREAL)
SELFTEST=st_$(DATATYPE)
TESTREAL=tr_$(DATATYPE)
ifeq "$(DATATYPE)" "short"
TYPEFLAGS=-DFIXED_POINT -Dkiss_fft_scalar=short
SELFTESTSRC=selftest_short.c
else
TYPEFLAGS=-Dkiss_fft_scalar=$(DATATYPE)
SELFTESTSRC=selftest.c
endif
CFLAGS=-Wall -O3 -ansi -pedantic -march=pentiumpro -ffast-math -fomit-frame-pointer
# If the above flags do not work, try the following
#CFLAGS=-Wall -O3 -ansi -pedantic
all: $(BENCHKISS) $(SELFTEST) $(BENCHFFTW) $(TESTREAL)
$(UTIL): ../kiss_fft.c ../kiss_fft2d.c fftutil.c
gcc -o $@ $(CFLAGS) -I.. $(TYPEFLAGS) ../kiss_fft.c ../kiss_fft2d.c fftutil.c -lm
#CFLAGS=-Wall -O3 -ansi -pedantic -march=pentiumpro -ffast-math -fomit-frame-pointer
# If the above flags do not work, try the following
CFLAGS=-Wall -O3
$(SELFTEST): ../kiss_fft.c $(SELFTESTSRC)
$(CC) -o $@ $(CFLAGS) -I.. $(TYPEFLAGS) -lm $+
$(TESTREAL): ../kiss_fft.c ../kiss_fftr.c test_real.c
gcc -o $@ $(CFLAGS) -I.. $(TYPEFLAGS) -lm $+
$(CC) -o $@ $(CFLAGS) -I.. $(TYPEFLAGS) -lm $+
$(BENCHKISS): benchkiss.c ../kiss_fft.c pstats.c
gcc -o $@ $(CFLAGS) -I.. benchkiss.c $(TYPEFLAGS) ../kiss_fft.c pstats.c -lm
fftw: $(BENCHFFTW)
./$(BENCHFFTW) -x $(NUMFFTS) -n $(NFFT)
$(CC) -o $@ $(CFLAGS) -I.. benchkiss.c $(TYPEFLAGS) ../kiss_fft.c pstats.c -lm
$(BENCHFFTW): benchfftw.c pstats.c
gcc -o $@ $(CFLAGS) -DDATATYPE$(DATATYPE) benchfftw.c pstats.c -lm -lfftw3f -lfftw3 -L /usr/local/lib/
time: all
@./$(BENCHKISS) -x $(NUMFFTS) -n $(NFFT)
@$(CC) -o $@ $(CFLAGS) -DDATATYPE$(DATATYPE) benchfftw.c pstats.c -lm -lfftw3f -lfftw3 -L /usr/local/lib/ || echo "FFTW not available for comparison"
POW2=256 512 1024 2048 4096 8192
POW3=243 729 2187
POW5=25 125 625 3125
mtime: all $(BENCHFFTW)
for n in $(POW2) $(POW3) $(POW5) ;do \
mtime: all
@for n in $(POW2) $(POW3) $(POW5) ;do \
echo ============================;\
./$(BENCHKISS) -x $(NUMFFTS) -n $$n;\
[ -x ./$(BENCHFFTW) ] && ./$(BENCHFFTW) -x $(NUMFFTS) -n $$n || true ; \
done
snr: all $(TESTREAL)
@echo "testkiss( $(NFFT) , 1, '$(DATATYPE)' );" | octave -q
@echo "testkiss( $(NFFT) , $(NROWS), '$(DATATYPE)' );" | octave -q
./$(TESTREAL)
test: all $(TESTREAL)
@echo "======SELF TEST"
@./$(SELFTEST)
@echo "======REAL FFT TEST"
@./$(TESTREAL)
@echo "======TIMING TEST"
@./$(BENCHKISS) -x $(NUMFFTS) -n $(NFFT)
@[ -x ./$(BENCHFFTW) ] && ./$(BENCHFFTW) -x $(NUMFFTS) -n $(NFFT) ||true
test: snr time fftw
selftest.c:
./mk_test.py 10 12 14 > selftest.c
selftest_short.c:
./mk_test.py -s 10 12 14 > selftest_short.c
clean:
rm -f *~ fftutil_* bm_* tr_* *.dat
rm -f *~ bm_* st_* tr_* *.dat

View File

@ -1,7 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <fftw3.h>
#include <getopt.h>
#include <unistd.h>
#include "pstats.h"
#ifdef DATATYPEdouble

View File

@ -1,6 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/times.h>
#include <unistd.h>
#include "kiss_fft.h"

0
fft.py → test/fft.py Normal file → Executable file
View File

View File

@ -1,19 +0,0 @@
function data = fileload( fname , prec , iscomplex ,nrows )
f = fopen(fname,"r", "native");
data = fread(f,Inf,prec);
fclose(f);
len = length(data);
if iscomplex,
data = (data(1:2:len) + j*data(2:2:len) );
len = len/2;
endif
tdata = zeros(len/nrows,nrows);
tdata(:) = data;
data = tdata .';
endfunction

View File

@ -1,20 +0,0 @@
function filesave( fname , prec , data )
# kiss fft stores data by rows
data = vec(data.');
len = length(data);
f = fopen(fname,"w", "native");
if is_complex(data),
flat=zeros( 1,2*len);
flat(1:2:2*len) = real(data);
flat(2:2:2*len) = imag(data);
data = flat;
endif
fwrite(f,data,prec);
fclose(f);
endfunction

View File

@ -23,6 +23,10 @@ def c_format(v,round=0):
def test_cpx( n,inverse ,short):
v = randvec(n,1)
scale = 1
if short:
minsnr=30
else:
minsnr=100
if inverse:
tvecout = FFT.inverse_fft(v)
@ -44,12 +48,13 @@ def test_cpx( n,inverse ,short):
kiss_fft_cpx test_vec_in[NFFT] = { """ + c_format(v) + """};
kiss_fft_cpx test_vec_out[NFFT] = {""" + c_format( tvecout ) + """};
kiss_fft_cpx testbuf[NFFT];
void * cfg = kiss_fft_alloc(NFFT,%d);""" % inverse + """
void * cfg = kiss_fft_alloc(NFFT,%d,0,0);""" % inverse + """
kiss_fft(cfg,test_vec_in,testbuf);
snr = snr_compare(test_vec_out,testbuf,NFFT);
printf("FFT n=%d, inverse=%d, snr = %g dB\\n",NFFT,""" + str(inverse) + """,snr);
printf("DATATYPE=" xstr(kiss_fft_scalar) ", FFT n=%d, inverse=%d, snr = %g dB\\n",NFFT,""" + str(inverse) + """,snr);
if (snr<""" + str(minsnr) + """)
exit_code++;
free(cfg);
}
#undef NFFT
@ -58,6 +63,8 @@ def test_cpx( n,inverse ,short):
def compare_func():
s="""
#define xstr(s) str(s)
#define str(s) #s
double snr_compare( kiss_fft_cpx * test_vec_out,kiss_fft_cpx * testbuf, int n)
{
int k;
@ -96,13 +103,13 @@ def main():
fftsizes = [ 1800 ]
print '#include "kiss_fft.h"'
print compare_func()
print "int main() {"
print "int main() { int exit_code=0;\n"
for n in fftsizes:
n = int(n)
print test_cpx(n,0,short)
print test_cpx(n,1,short)
print """
return 0;
return exit_code;
}
"""

View File

@ -1,5 +1,6 @@
#include "kiss_fft.h"
#include "_kiss_fft_guts.h"
#include <sys/times.h>
#include <time.h>
#include <unistd.h>
static double cputime()
@ -9,8 +10,6 @@ static double cputime()
return (double)(t.tms_utime + t.tms_stime)/ sysconf(_SC_CLK_TCK) ;
}
double snr_compare( kiss_fft_cpx * vec1,kiss_fft_cpx * vec2, int n)
{
int k;
@ -18,15 +17,19 @@ double snr_compare( kiss_fft_cpx * vec1,kiss_fft_cpx * vec2, int n)
sigpow = noisepow = .00000000000000000001;
for (k=0;k<n;++k) {
sigpow += vec1[k].r * vec1[k].r +
vec1[k].i * vec1[k].i;
err = vec1[k].r - vec2[k].r;
sigpow += (double)vec1[k].r * (double)vec1[k].r +
(double)vec1[k].i * (double)vec1[k].i;
err = (double)vec1[k].r - (double)vec2[k].r;
noisepow += err * err;
err = vec1[k].i - vec2[k].i;
err = (double)vec1[k].i - (double)vec2[k].i;
noisepow += err * err;
if (vec1[k].r)
scale += vec2[k].r / vec1[k].r;
scale +=(double) vec2[k].r / (double)vec1[k].r;
/*
fprintf(stderr,"vec1=");pcpx(vec1+k);
fprintf(stderr,"vec2=");pcpx(vec2+k);
*/
}
snr = 10*log10( sigpow / noisepow );
scale /= n;
@ -38,17 +41,13 @@ double snr_compare( kiss_fft_cpx * vec1,kiss_fft_cpx * vec2, int n)
#ifndef RANDOM
#define NFFT 8
#else
#define NFFT 2*3*5*7*11
#define NFFT 8*3*5
#endif
#ifndef NUMFFTS
#define NUMFFTS 1000
#endif
void pcpx(const char * msg, kiss_fft_cpx * c)
{
printf("%s: %g + %gi\n",msg,c->r,c->i);
}
int main()
{
@ -62,6 +61,7 @@ int main()
void * kiss_fft_state;
void * kiss_fftr_state;
srand(time(0));
for (i=0;i<NFFT;++i) {
#ifdef RANDOM
@ -69,7 +69,6 @@ int main()
#endif
cin[i].r = sin[i];
cin[i].i = 0;
/* printf("in[%d]",i);pcpx("",cin+i); */
}
kiss_fft_state = kiss_fft_alloc(NFFT,0,0,0);
@ -106,9 +105,6 @@ int main()
for (i=0;i<NFFT;++i) {
sout[i].r = sin[i];
sout[i].i = 0;
/* printf("sin[%d] = %f\t",i,sin[i]);
printf("cin[%d]",i);pcpx("",cin+i);
printf("sout[%d]",i);pcpx("",sout+i); */
}
printf( "nfft=%d, inverse=%d, snr=%g\n",

View File

@ -1,58 +0,0 @@
function snr= testkiss( nfft , nrows, prec )
printf('### testing SNR for %d x %d point %s FFTs\n' , nfft,nrows,prec);
if strcmp( prec ,'short')
scale_t2f=nfft*nrows;
scale_f2t=nfft*nrows;
else
scale_t2f=1;
scale_f2t=1/(nfft*nrows);
endif
kfft= sprintf('./fftutil_%s',prec);
sig=floor(32767*rand(nrows,nfft)) + j*floor(32767*rand(nrows,nfft));
filesave('time.dat',prec,sig);
if nrows > 1
cmd = sprintf('%s -r %d -n %d time.dat freq.dat',kfft,nrows,nfft);
else
cmd = sprintf('%s -n %d time.dat freq.dat',kfft,nfft);
endif
system(cmd);
Fsigcomp=fileload('freq.dat',prec,1,nrows ) * scale_t2f;
if nrows == 1,
Fsig=fft(sig);
else
Fsig=fft2(sig);
endif
diff = Fsig - Fsigcomp;
noise_pow = sum( conj(diff).*diff );
sig_pow = sum( conj(Fsig).*Fsig );
snr_t2f = 10*log10( sig_pow / noise_pow )
avg_scale = mean( abs(Fsig) ./ abs(Fsigcomp) );
var_scale = var( abs(Fsig) ./ abs(Fsigcomp) );
if nrows > 1
cmd = sprintf('%s -r %d -i -n %d freq.dat time2.dat',kfft,nrows,nfft);
else
cmd = sprintf('%s -i -n %d freq.dat time2.dat',kfft,nfft);
endif
system(cmd);
sigcomp=fileload('time2.dat',prec,1,nrows) * scale_f2t;
diff = sig - sigcomp;
noise_pow = sum( conj(diff).*diff );
sig_pow = sum( conj(sig).*sig );
snr_f2t = 10*log10( sig_pow / noise_pow )
avg_scale = mean( abs(sig) ./ abs(sigcomp) );
var_scale = var( abs(sig) ./ abs(sigcomp) );
snr=[snr_t2f snr_f2t];
endfunction

File diff suppressed because one or more lines are too long

View File

@ -10,58 +10,61 @@ ifeq "$(DATATYPE)" ""
DATATYPE=float
endif
UTIL=fftutil_$(DATATYPE)
TESTREAL=tr_$(DATATYPE)
BENCHKISS=bm_kiss_$(DATATYPE)
BENCHFFTW=bm_fftw_$(DATATYPE)
all: $(UTIL) $(BENCHKISS) $(TESTREAL)
SELFTEST=st_$(DATATYPE)
TESTREAL=tr_$(DATATYPE)
ifeq "$(DATATYPE)" "short"
TYPEFLAGS=-DFIXED_POINT -Dkiss_fft_scalar=short
SELFTESTSRC=selftest_short.c
else
TYPEFLAGS=-Dkiss_fft_scalar=$(DATATYPE)
SELFTESTSRC=selftest.c
endif
CFLAGS=-Wall -O3 -ansi -pedantic -march=pentiumpro -ffast-math -fomit-frame-pointer
# If the above flags do not work, try the following
#CFLAGS=-Wall -O3 -ansi -pedantic
all: $(BENCHKISS) $(SELFTEST) $(BENCHFFTW) $(TESTREAL)
$(UTIL): ../kiss_fft.c ../kiss_fft2d.c fftutil.c
gcc -o $@ $(CFLAGS) -I.. $(TYPEFLAGS) ../kiss_fft.c ../kiss_fft2d.c fftutil.c -lm
#CFLAGS=-Wall -O3 -ansi -pedantic -march=pentiumpro -ffast-math -fomit-frame-pointer
# If the above flags do not work, try the following
CFLAGS=-Wall -O3
$(SELFTEST): ../kiss_fft.c $(SELFTESTSRC)
$(CC) -o $@ $(CFLAGS) -I.. $(TYPEFLAGS) -lm $+
$(TESTREAL): ../kiss_fft.c ../kiss_fftr.c test_real.c
gcc -o $@ $(CFLAGS) -I.. $(TYPEFLAGS) -lm $+
$(CC) -o $@ $(CFLAGS) -I.. $(TYPEFLAGS) -lm $+
$(BENCHKISS): benchkiss.c ../kiss_fft.c pstats.c
gcc -o $@ $(CFLAGS) -I.. benchkiss.c $(TYPEFLAGS) ../kiss_fft.c pstats.c -lm
fftw: $(BENCHFFTW)
./$(BENCHFFTW) -x $(NUMFFTS) -n $(NFFT)
$(CC) -o $@ $(CFLAGS) -I.. benchkiss.c $(TYPEFLAGS) ../kiss_fft.c pstats.c -lm
$(BENCHFFTW): benchfftw.c pstats.c
gcc -o $@ $(CFLAGS) -DDATATYPE$(DATATYPE) benchfftw.c pstats.c -lm -lfftw3f -lfftw3 -L /usr/local/lib/
time: all
@./$(BENCHKISS) -x $(NUMFFTS) -n $(NFFT)
@$(CC) -o $@ $(CFLAGS) -DDATATYPE$(DATATYPE) benchfftw.c pstats.c -lm -lfftw3f -lfftw3 -L /usr/local/lib/ || echo "FFTW not available for comparison"
POW2=256 512 1024 2048 4096 8192
POW3=243 729 2187
POW5=25 125 625 3125
mtime: all $(BENCHFFTW)
for n in $(POW2) $(POW3) $(POW5) ;do \
mtime: all
@for n in $(POW2) $(POW3) $(POW5) ;do \
echo ============================;\
./$(BENCHKISS) -x $(NUMFFTS) -n $$n;\
[ -x ./$(BENCHFFTW) ] && ./$(BENCHFFTW) -x $(NUMFFTS) -n $$n || true ; \
done
snr: all $(TESTREAL)
@echo "testkiss( $(NFFT) , 1, '$(DATATYPE)' );" | octave -q
@echo "testkiss( $(NFFT) , $(NROWS), '$(DATATYPE)' );" | octave -q
./$(TESTREAL)
test: all $(TESTREAL)
@echo "======SELF TEST"
@./$(SELFTEST)
@echo "======REAL FFT TEST"
@./$(TESTREAL)
@echo "======TIMING TEST"
@./$(BENCHKISS) -x $(NUMFFTS) -n $(NFFT)
@[ -x ./$(BENCHFFTW) ] && ./$(BENCHFFTW) -x $(NUMFFTS) -n $(NFFT) ||true
test: snr time fftw
selftest.c:
./mk_test.py 10 12 14 > selftest.c
selftest_short.c:
./mk_test.py -s 10 12 14 > selftest_short.c
clean:
rm -f *~ fftutil_* bm_* tr_* *.dat
rm -f *~ bm_* st_* tr_* *.dat

View File

@ -16,7 +16,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#include "kiss_fft.h"