Mercurial > hg > qm-dsp
comparison ext/kissfft/test/testkiss.py @ 409:1f1999b0f577
Bring in kissfft into this repo (formerly a subrepo, but the remote is not responding)
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Tue, 21 Jul 2015 07:34:15 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
408:5316fa4b0f33 | 409:1f1999b0f577 |
---|---|
1 #!/usr/bin/env python | |
2 | |
3 import math | |
4 import sys | |
5 import os | |
6 import random | |
7 import struct | |
8 import popen2 | |
9 import getopt | |
10 import numpy | |
11 | |
12 pi=math.pi | |
13 e=math.e | |
14 j=complex(0,1) | |
15 | |
16 doreal=0 | |
17 | |
18 datatype = os.environ.get('DATATYPE','float') | |
19 | |
20 util = '../tools/fft_' + datatype | |
21 minsnr=90 | |
22 if datatype == 'double': | |
23 fmt='d' | |
24 elif datatype=='int16_t': | |
25 fmt='h' | |
26 minsnr=10 | |
27 elif datatype=='int32_t': | |
28 fmt='i' | |
29 elif datatype=='simd': | |
30 fmt='4f' | |
31 sys.stderr.write('testkiss.py does not yet test simd') | |
32 sys.exit(0) | |
33 elif datatype=='float': | |
34 fmt='f' | |
35 else: | |
36 sys.stderr.write('unrecognized datatype %s\n' % datatype) | |
37 sys.exit(1) | |
38 | |
39 | |
40 def dopack(x,cpx=1): | |
41 x = numpy.reshape( x, ( numpy.size(x),) ) | |
42 | |
43 if cpx: | |
44 s = ''.join( [ struct.pack(fmt*2,c.real,c.imag) for c in x ] ) | |
45 else: | |
46 s = ''.join( [ struct.pack(fmt,c.real) for c in x ] ) | |
47 return s | |
48 | |
49 def dounpack(x,cpx): | |
50 uf = fmt * ( len(x) / struct.calcsize(fmt) ) | |
51 s = struct.unpack(uf,x) | |
52 if cpx: | |
53 return numpy.array(s[::2]) + numpy.array( s[1::2] )*j | |
54 else: | |
55 return numpy.array(s ) | |
56 | |
57 def make_random(dims=[1]): | |
58 res = [] | |
59 for i in range(dims[0]): | |
60 if len(dims)==1: | |
61 r=random.uniform(-1,1) | |
62 if doreal: | |
63 res.append( r ) | |
64 else: | |
65 i=random.uniform(-1,1) | |
66 res.append( complex(r,i) ) | |
67 else: | |
68 res.append( make_random( dims[1:] ) ) | |
69 return numpy.array(res) | |
70 | |
71 def flatten(x): | |
72 ntotal = numpy.size(x) | |
73 return numpy.reshape(x,(ntotal,)) | |
74 | |
75 def randmat( ndims ): | |
76 dims=[] | |
77 for i in range( ndims ): | |
78 curdim = int( random.uniform(2,5) ) | |
79 if doreal and i==(ndims-1): | |
80 curdim = int(curdim/2)*2 # force even last dimension if real | |
81 dims.append( curdim ) | |
82 return make_random(dims ) | |
83 | |
84 def test_fft(ndims): | |
85 x=randmat( ndims ) | |
86 | |
87 | |
88 if doreal: | |
89 xver = numpy.fft.rfftn(x) | |
90 else: | |
91 xver = numpy.fft.fftn(x) | |
92 | |
93 open('/tmp/fftexp.dat','w').write(dopack( flatten(xver) , True ) ) | |
94 | |
95 x2=dofft(x,doreal) | |
96 err = xver - x2 | |
97 errf = flatten(err) | |
98 xverf = flatten(xver) | |
99 errpow = numpy.vdot(errf,errf)+1e-10 | |
100 sigpow = numpy.vdot(xverf,xverf)+1e-10 | |
101 snr = 10*math.log10(abs(sigpow/errpow) ) | |
102 print 'SNR (compared to NumPy) : %.1fdB' % float(snr) | |
103 | |
104 if snr<minsnr: | |
105 print 'xver=',xver | |
106 print 'x2=',x2 | |
107 print 'err',err | |
108 sys.exit(1) | |
109 | |
110 def dofft(x,isreal): | |
111 dims=list( numpy.shape(x) ) | |
112 x = flatten(x) | |
113 | |
114 scale=1 | |
115 if datatype=='int16_t': | |
116 x = 32767 * x | |
117 scale = len(x) / 32767.0 | |
118 elif datatype=='int32_t': | |
119 x = 2147483647.0 * x | |
120 scale = len(x) / 2147483647.0 | |
121 | |
122 cmd='%s -n ' % util | |
123 cmd += ','.join([str(d) for d in dims]) | |
124 if doreal: | |
125 cmd += ' -R ' | |
126 | |
127 print cmd | |
128 p = popen2.Popen3(cmd ) | |
129 | |
130 open('/tmp/fftin.dat','w').write(dopack( x , isreal==False ) ) | |
131 | |
132 p.tochild.write( dopack( x , isreal==False ) ) | |
133 p.tochild.close() | |
134 | |
135 res = dounpack( p.fromchild.read() , 1 ) | |
136 open('/tmp/fftout.dat','w').write(dopack( flatten(res) , True ) ) | |
137 if doreal: | |
138 dims[-1] = int( dims[-1]/2 ) + 1 | |
139 | |
140 res = scale * res | |
141 | |
142 p.wait() | |
143 return numpy.reshape(res,dims) | |
144 | |
145 def main(): | |
146 opts,args = getopt.getopt(sys.argv[1:],'r') | |
147 opts=dict(opts) | |
148 | |
149 global doreal | |
150 doreal = opts.has_key('-r') | |
151 | |
152 if doreal: | |
153 print 'Testing multi-dimensional real FFTs' | |
154 else: | |
155 print 'Testing multi-dimensional FFTs' | |
156 | |
157 for dim in range(1,4): | |
158 test_fft( dim ) | |
159 | |
160 if __name__ == "__main__": | |
161 main() | |
162 |