summaryrefslogtreecommitdiff
path: root/dl/sp/src/test/test_util_fft.c
blob: 025ee8d3fe6f9405bce2f90994db643d17babb27 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#include "dl/sp/src/test/test_util.h"

#include "dl/sp/src/test/compare.h"
#include "dl/sp/src/test/gensig.h"

/*
 * Test results from running either forward or inverse FFT tests
 */
struct TestResult {
  /* Number of tests that failed */
  int failed_count_;

  /* Number of tests run */
  int test_count_;

  /* Number of tests that were expected to fail */
  int expected_failure_count_;

  /* Number of tests that were expected to fail but didn't */
  int unexpected_pass_count_;

  /* Number of tests that unexpectedly failed */
  int unexpected_failure_count_;

  /* The minimum SNR found for all of the tests */
  float min_snr_;
};

/*
 * Run one FFT test
 */
void TestOneFFT(int fft_log_size,
                int signal_type,
                float signal_value,
                const struct TestInfo* info,
                const char* message) {
  struct SnrResult snr;

  if (info->do_forward_tests_) {
    RunOneForwardTest(fft_log_size, signal_type, signal_value, &snr);
    printf("Forward %s\n", message);
    printf("SNR:  real part    %10.3f dB\n", snr.real_snr_);
    printf("      imag part    %10.3f dB\n", snr.imag_snr_);
    printf("      complex part %10.3f dB\n", snr.complex_snr_);
  }

  if (info->do_inverse_tests_) {
    RunOneInverseTest(fft_log_size, signal_type, signal_value, &snr);
    printf("Inverse %s\n", message);
    if (info->real_only_) {
      printf("SNR:  real         %10.3f dB\n", snr.real_snr_);
    } else {
      printf("SNR:  real part    %10.3f dB\n", snr.real_snr_);
      printf("      imag part    %10.3f dB\n", snr.imag_snr_);
      printf("      complex part %10.3f dB\n", snr.complex_snr_);
    }
  }
}

/*
 * Run a set of tests, printing out the result of each test.
 */
void RunTests(struct TestResult* result,
              float (*test_function)(int, int, float, struct SnrResult*),
              const char* id,
              int is_inverse_test,
              const struct TestInfo* info,
              float snr_threshold) {
  int fft_order;
  int signal_type;
  float snr;
  int tests = 0;
  int failures = 0;
  int expected_failures = 0;
  int unexpected_failures = 0;
  int unexpected_passes = 0;
  float min_snr = 1e10;
  struct SnrResult snrResults;

  for (fft_order = info->min_fft_order_; fft_order <= info->max_fft_order_;
       ++fft_order) {
    for (signal_type = 0; signal_type < MaxSignalType(info->real_only_);
         ++signal_type) {
      int known_failure = 0;
      int test_failed = 0;
      ++tests;
      snr = test_function(fft_order, signal_type, 1024.0, &snrResults);
      if (snr < min_snr)
        min_snr = snr;
      known_failure = IsKnownFailure(fft_order, is_inverse_test,
                                     signal_type, info->known_failures_);
      if (snr < snr_threshold) {
        ++failures;
        test_failed = 1;
        if (known_failure) {
          ++expected_failures;
          printf(" *FAILED: %s ", id);
        } else {
          ++unexpected_failures;
          printf("**FAILED: %s ", id);
        }
      } else {
        test_failed = 0;
        printf("  PASSED: %s ", id);
      }
      printf("order %2d signal %d:  SNR = %9.3f",
             fft_order, signal_type, snr);
      if (known_failure) {
        if (test_failed) {
          printf(" (expected failure)");
        } else {
          ++unexpected_passes;
          printf(" (**Expected to fail, but passed)");
        }
      }
      printf("\n");
    }
  }

  printf("%sSummary:  %d %s tests failed out of %d tests. "
         "(Success rate %.2f%%.)\n",
         failures ? "**" : "",
         failures,
         id,
         tests,
         (100.0 * (tests - failures)) / tests);
  if (expected_failures || unexpected_passes || unexpected_failures) {
    printf("    (%d expected failures)\n", expected_failures);
    printf("    (%d unexpected failures)\n", unexpected_failures);
    printf("    (%d unexpected passes)\n", unexpected_passes);
  }
  
  printf("    (Minimum SNR = %.3f dB)\n", min_snr);

  result->failed_count_ = failures;
  result->test_count_ = tests;
  result->expected_failure_count_ = expected_failures;
  result->unexpected_pass_count_ = unexpected_passes;
  result->unexpected_failure_count_ = unexpected_failures;
  result->min_snr_ = min_snr;
}

/*
 * For all FFT orders and signal types, run the forward FFT.
 * runOneForwardTest must be defined to compute the forward FFT and
 * return the SNR beween the actual and expected FFT.
 *
 * Also finds the minium SNR from all of the tests and returns the
 * minimum SNR value.
 */
void RunForwardTests(struct TestResult* result, const struct TestInfo* info,
                     float snr_threshold) {
  RunTests(result, RunOneForwardTest, "FwdFFT", 0, info, snr_threshold);
}

void initializeTestResult(struct TestResult *result) {
  result->failed_count_ = 0;
  result->test_count_ = 0;
  result->expected_failure_count_ = 0;
  result->min_snr_ = 1000;
}

/*
 * For all FFT orders and signal types, run the inverse FFT.
 * runOneInverseTest must be defined to compute the forward FFT and
 * return the SNR beween the actual and expected FFT.
 *
 * Also finds the minium SNR from all of the tests and returns the
 * minimum SNR value.
 */
void RunInverseTests(struct TestResult* result, const struct TestInfo* info,
                     float snr_threshold) {
  RunTests(result, RunOneInverseTest, "InvFFT", 1, info, snr_threshold);
}

/*
 * Run all forward and inverse FFT tests, printing a summary of the
 * results.
 */
int RunAllTests(const struct TestInfo* info) {
  int failed;
  int total;
  float min_forward_snr;
  float min_inverse_snr;
  struct TestResult forward_results;
  struct TestResult inverse_results;

  initializeTestResult(&forward_results);
  initializeTestResult(&inverse_results);

  if (info->do_forward_tests_)
    RunForwardTests(&forward_results, info, info->forward_threshold_);
  if (info->do_inverse_tests_)
    RunInverseTests(&inverse_results, info, info->inverse_threshold_);

  failed = forward_results.failed_count_ + inverse_results.failed_count_;
  total = forward_results.test_count_ + inverse_results.test_count_;
  min_forward_snr = forward_results.min_snr_;
  min_inverse_snr = inverse_results.min_snr_;

  if (total) {
    printf("%sTotal: %d tests failed out of %d tests.  "
           "(Success rate = %.2f%%.)\n",
           failed ? "**" : "",
           failed,
           total,
           (100.0 * (total - failed)) / total);
    if (forward_results.expected_failure_count_
        + inverse_results.expected_failure_count_) {
      printf("  (%d expected failures)\n",
             forward_results.expected_failure_count_
             + inverse_results.expected_failure_count_);
      printf("  (%d unexpected failures)\n",
             forward_results.unexpected_failure_count_
             + inverse_results.unexpected_failure_count_);
      printf("  (%d unexpected passes)\n",
             forward_results.unexpected_pass_count_
             + inverse_results.unexpected_pass_count_);
    }
    printf("  Min forward SNR = %.3f dB, min inverse SNR = %.3f dB\n",
           min_forward_snr,
           min_inverse_snr);
  } else {
    printf("No tests run\n");
  }

  return failed;
}