test_real.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #include "kiss_fftr.h"
  2. #include "_kiss_fft_guts.h"
  3. #include <sys/times.h>
  4. #include <time.h>
  5. #include <unistd.h>
  6. static double cputime(void)
  7. {
  8. struct tms t;
  9. times(&t);
  10. return (double)(t.tms_utime + t.tms_stime)/ sysconf(_SC_CLK_TCK) ;
  11. }
  12. static
  13. kiss_fft_scalar rand_scalar(void)
  14. {
  15. #ifdef USE_SIMD
  16. return _mm_set1_ps(rand()-RAND_MAX/2);
  17. #else
  18. kiss_fft_scalar s = (kiss_fft_scalar)(rand() -RAND_MAX/2);
  19. return s/2;
  20. #endif
  21. }
  22. static
  23. double snr_compare( kiss_fft_cpx * vec1,kiss_fft_cpx * vec2, int n)
  24. {
  25. int k;
  26. double sigpow=1e-10,noisepow=1e-10,err,snr,scale=0;
  27. #ifdef USE_SIMD
  28. float *fv1 = (float*)vec1;
  29. float *fv2 = (float*)vec2;
  30. for (k=0;k<8*n;++k) {
  31. sigpow += *fv1 * *fv1;
  32. err = *fv1 - *fv2;
  33. noisepow += err*err;
  34. ++fv1;
  35. ++fv2;
  36. }
  37. #else
  38. for (k=0;k<n;++k) {
  39. sigpow += (double)vec1[k].r * (double)vec1[k].r +
  40. (double)vec1[k].i * (double)vec1[k].i;
  41. err = (double)vec1[k].r - (double)vec2[k].r;
  42. noisepow += err * err;
  43. err = (double)vec1[k].i - (double)vec2[k].i;
  44. noisepow += err * err;
  45. if (vec1[k].r)
  46. scale +=(double) vec2[k].r / (double)vec1[k].r;
  47. }
  48. #endif
  49. snr = 10*log10( sigpow / noisepow );
  50. scale /= n;
  51. if (snr<10) {
  52. printf( "\npoor snr, try a scaling factor %f\n" , scale );
  53. exit(1);
  54. }
  55. return snr;
  56. }
  57. #ifndef NUMFFTS
  58. #define NUMFFTS 10000
  59. #endif
  60. int main(int argc,char ** argv)
  61. {
  62. int nfft = 8*3*5;
  63. double ts,tfft,trfft;
  64. int i;
  65. if (argc>1)
  66. nfft = atoi(argv[1]);
  67. kiss_fft_cpx cin[nfft];
  68. kiss_fft_cpx cout[nfft];
  69. kiss_fft_cpx sout[nfft];
  70. kiss_fft_cfg kiss_fft_state;
  71. kiss_fftr_cfg kiss_fftr_state;
  72. kiss_fft_scalar rin[nfft+2];
  73. kiss_fft_scalar rout[nfft+2];
  74. kiss_fft_scalar zero;
  75. memset(&zero,0,sizeof(zero) ); // ugly way of setting short,int,float,double, or __m128 to zero
  76. srand(time(0));
  77. for (i=0;i<nfft;++i) {
  78. rin[i] = rand_scalar();
  79. cin[i].r = rin[i];
  80. cin[i].i = zero;
  81. }
  82. kiss_fft_state = kiss_fft_alloc(nfft,0,0,0);
  83. kiss_fftr_state = kiss_fftr_alloc(nfft,0,0,0);
  84. kiss_fft(kiss_fft_state,cin,cout);
  85. kiss_fftr(kiss_fftr_state,rin,sout);
  86. /*
  87. printf(" results from kiss_fft : (%f,%f), (%f,%f), (%f,%f) ...\n "
  88. , (float)cout[0].r , (float)cout[0].i
  89. , (float)cout[1].r , (float)cout[1].i
  90. , (float)cout[2].r , (float)cout[2].i);
  91. printf(" results from kiss_fftr: (%f,%f), (%f,%f), (%f,%f) ...\n "
  92. , (float)sout[0].r , (float)sout[0].i
  93. , (float)sout[1].r , (float)sout[1].i
  94. , (float)sout[2].r , (float)sout[2].i);
  95. */
  96. printf( "nfft=%d, inverse=%d, snr=%g\n",
  97. nfft,0, snr_compare(cout,sout,(nfft/2)+1) );
  98. ts = cputime();
  99. for (i=0;i<NUMFFTS;++i) {
  100. kiss_fft(kiss_fft_state,cin,cout);
  101. }
  102. tfft = cputime() - ts;
  103. ts = cputime();
  104. for (i=0;i<NUMFFTS;++i) {
  105. kiss_fftr( kiss_fftr_state, rin, cout );
  106. /* kiss_fftri(kiss_fftr_state,cout,rin); */
  107. }
  108. trfft = cputime() - ts;
  109. printf("%d complex ffts took %gs, real took %gs\n",NUMFFTS,tfft,trfft);
  110. free(kiss_fft_state);
  111. free(kiss_fftr_state);
  112. kiss_fft_state = kiss_fft_alloc(nfft,1,0,0);
  113. kiss_fftr_state = kiss_fftr_alloc(nfft,1,0,0);
  114. memset(cin,0,sizeof(cin));
  115. #if 1
  116. for (i=1;i< nfft/2;++i) {
  117. //cin[i].r = (kiss_fft_scalar)(rand()-RAND_MAX/2);
  118. cin[i].r = rand_scalar();
  119. cin[i].i = rand_scalar();
  120. }
  121. #else
  122. cin[0].r = 12000;
  123. cin[3].r = 12000;
  124. cin[nfft/2].r = 12000;
  125. #endif
  126. // conjugate symmetry of real signal
  127. for (i=1;i< nfft/2;++i) {
  128. cin[nfft-i].r = cin[i].r;
  129. cin[nfft-i].i = - cin[i].i;
  130. }
  131. kiss_fft(kiss_fft_state,cin,cout);
  132. kiss_fftri(kiss_fftr_state,cin,rout);
  133. /*
  134. printf(" results from inverse kiss_fft : (%f,%f), (%f,%f), (%f,%f), (%f,%f), (%f,%f) ...\n "
  135. , (float)cout[0].r , (float)cout[0].i , (float)cout[1].r , (float)cout[1].i , (float)cout[2].r , (float)cout[2].i , (float)cout[3].r , (float)cout[3].i , (float)cout[4].r , (float)cout[4].i
  136. );
  137. printf(" results from inverse kiss_fftr: %f,%f,%f,%f,%f ... \n"
  138. ,(float)rout[0] ,(float)rout[1] ,(float)rout[2] ,(float)rout[3] ,(float)rout[4]);
  139. */
  140. for (i=0;i<nfft;++i) {
  141. sout[i].r = rout[i];
  142. sout[i].i = zero;
  143. }
  144. printf( "nfft=%d, inverse=%d, snr=%g\n",
  145. nfft,1, snr_compare(cout,sout,nfft/2) );
  146. free(kiss_fft_state);
  147. free(kiss_fftr_state);
  148. return 0;
  149. }