testkiss.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #!/usr/bin/env python
  2. import math
  3. import sys
  4. import os
  5. import random
  6. import struct
  7. import popen2
  8. import getopt
  9. import numpy
  10. pi=math.pi
  11. e=math.e
  12. j=complex(0,1)
  13. doreal=0
  14. datatype = os.environ.get('DATATYPE','float')
  15. util = '../tools/fft_' + datatype
  16. minsnr=90
  17. if datatype == 'double':
  18. fmt='d'
  19. elif datatype=='int16_t':
  20. fmt='h'
  21. minsnr=10
  22. elif datatype=='int32_t':
  23. fmt='i'
  24. elif datatype=='simd':
  25. fmt='4f'
  26. sys.stderr.write('testkiss.py does not yet test simd')
  27. sys.exit(0)
  28. elif datatype=='float':
  29. fmt='f'
  30. else:
  31. sys.stderr.write('unrecognized datatype %s\n' % datatype)
  32. sys.exit(1)
  33. def dopack(x,cpx=1):
  34. x = numpy.reshape( x, ( numpy.size(x),) )
  35. if cpx:
  36. s = ''.join( [ struct.pack(fmt*2,c.real,c.imag) for c in x ] )
  37. else:
  38. s = ''.join( [ struct.pack(fmt,c.real) for c in x ] )
  39. return s
  40. def dounpack(x,cpx):
  41. uf = fmt * ( len(x) / struct.calcsize(fmt) )
  42. s = struct.unpack(uf,x)
  43. if cpx:
  44. return numpy.array(s[::2]) + numpy.array( s[1::2] )*j
  45. else:
  46. return numpy.array(s )
  47. def make_random(dims=[1]):
  48. res = []
  49. for i in range(dims[0]):
  50. if len(dims)==1:
  51. r=random.uniform(-1,1)
  52. if doreal:
  53. res.append( r )
  54. else:
  55. i=random.uniform(-1,1)
  56. res.append( complex(r,i) )
  57. else:
  58. res.append( make_random( dims[1:] ) )
  59. return numpy.array(res)
  60. def flatten(x):
  61. ntotal = numpy.size(x)
  62. return numpy.reshape(x,(ntotal,))
  63. def randmat( ndims ):
  64. dims=[]
  65. for i in range( ndims ):
  66. curdim = int( random.uniform(2,5) )
  67. if doreal and i==(ndims-1):
  68. curdim = int(curdim/2)*2 # force even last dimension if real
  69. dims.append( curdim )
  70. return make_random(dims )
  71. def test_fft(ndims):
  72. x=randmat( ndims )
  73. if doreal:
  74. xver = numpy.fft.rfftn(x)
  75. else:
  76. xver = numpy.fft.fftn(x)
  77. open('/tmp/fftexp.dat','w').write(dopack( flatten(xver) , True ) )
  78. x2=dofft(x,doreal)
  79. err = xver - x2
  80. errf = flatten(err)
  81. xverf = flatten(xver)
  82. errpow = numpy.vdot(errf,errf)+1e-10
  83. sigpow = numpy.vdot(xverf,xverf)+1e-10
  84. snr = 10*math.log10(abs(sigpow/errpow) )
  85. print 'SNR (compared to NumPy) : %.1fdB' % float(snr)
  86. if snr<minsnr:
  87. print 'xver=',xver
  88. print 'x2=',x2
  89. print 'err',err
  90. sys.exit(1)
  91. def dofft(x,isreal):
  92. dims=list( numpy.shape(x) )
  93. x = flatten(x)
  94. scale=1
  95. if datatype=='int16_t':
  96. x = 32767 * x
  97. scale = len(x) / 32767.0
  98. elif datatype=='int32_t':
  99. x = 2147483647.0 * x
  100. scale = len(x) / 2147483647.0
  101. cmd='%s -n ' % util
  102. cmd += ','.join([str(d) for d in dims])
  103. if doreal:
  104. cmd += ' -R '
  105. print cmd
  106. p = popen2.Popen3(cmd )
  107. open('/tmp/fftin.dat','w').write(dopack( x , isreal==False ) )
  108. p.tochild.write( dopack( x , isreal==False ) )
  109. p.tochild.close()
  110. res = dounpack( p.fromchild.read() , 1 )
  111. open('/tmp/fftout.dat','w').write(dopack( flatten(res) , True ) )
  112. if doreal:
  113. dims[-1] = int( dims[-1]/2 ) + 1
  114. res = scale * res
  115. p.wait()
  116. return numpy.reshape(res,dims)
  117. def main():
  118. opts,args = getopt.getopt(sys.argv[1:],'r')
  119. opts=dict(opts)
  120. global doreal
  121. doreal = opts.has_key('-r')
  122. if doreal:
  123. print 'Testing multi-dimensional real FFTs'
  124. else:
  125. print 'Testing multi-dimensional FFTs'
  126. for dim in range(1,4):
  127. test_fft( dim )
  128. if __name__ == "__main__":
  129. main()