1 | |
---|
2 | //#define WANT_STREAM |
---|
3 | #define WANT_MATH |
---|
4 | |
---|
5 | #include "include.h" |
---|
6 | |
---|
7 | #include "newmatap.h" |
---|
8 | |
---|
9 | //#include "newmatio.h" |
---|
10 | |
---|
11 | #include "tmt.h" |
---|
12 | |
---|
13 | #ifdef use_namespace |
---|
14 | using namespace NEWMAT; |
---|
15 | #endif |
---|
16 | |
---|
17 | |
---|
18 | |
---|
19 | static void SlowFT(const ColumnVector& a, const ColumnVector&b, |
---|
20 | ColumnVector& x, ColumnVector& y) |
---|
21 | { |
---|
22 | int n = a.Nrows(); |
---|
23 | x.ReSize(n); y.ReSize(n); |
---|
24 | Real f = 6.2831853071795864769/n; |
---|
25 | for (int j=1; j<=n; j++) |
---|
26 | { |
---|
27 | Real sumx = 0.0; Real sumy = 0.0; |
---|
28 | for (int k=1; k<=n; k++) |
---|
29 | { |
---|
30 | Real theta = - (j-1) * (k-1) * f; |
---|
31 | Real c = cos(theta); Real s = sin(theta); |
---|
32 | sumx += c * a(k) - s * b(k); sumy += s * a(k) + c * b(k); |
---|
33 | } |
---|
34 | x(j) = sumx; y(j) = sumy; |
---|
35 | } |
---|
36 | } |
---|
37 | |
---|
38 | static void SlowDTT_II(const ColumnVector& a, ColumnVector& c, ColumnVector& s) |
---|
39 | { |
---|
40 | int n = a.Nrows(); c.ReSize(n); s.ReSize(n); |
---|
41 | Real f = 6.2831853071795864769 / (4*n); |
---|
42 | int k; |
---|
43 | |
---|
44 | for (k=1; k<=n; k++) |
---|
45 | { |
---|
46 | Real sum = 0.0; |
---|
47 | const int k1 = k-1; // otherwise Visual C++ 5 fails |
---|
48 | for (int j=1; j<=n; j++) sum += cos(k1 * (2*j-1) * f) * a(j); |
---|
49 | c(k) = sum; |
---|
50 | } |
---|
51 | |
---|
52 | for (k=1; k<=n; k++) |
---|
53 | { |
---|
54 | Real sum = 0.0; |
---|
55 | for (int j=1; j<=n; j++) sum += sin(k * (2*j-1) * f) * a(j); |
---|
56 | s(k) = sum; |
---|
57 | } |
---|
58 | } |
---|
59 | |
---|
60 | static void SlowDTT(const ColumnVector& a, ColumnVector& c, ColumnVector& s) |
---|
61 | { |
---|
62 | int n1 = a.Nrows(); int n = n1 - 1; |
---|
63 | c.ReSize(n1); s.ReSize(n1); |
---|
64 | Real f = 6.2831853071795864769 / (2*n); |
---|
65 | int k; |
---|
66 | |
---|
67 | int sign = 1; |
---|
68 | for (k=1; k<=n1; k++) |
---|
69 | { |
---|
70 | Real sum = 0.0; |
---|
71 | for (int j=2; j<=n; j++) sum += cos((j-1) * (k-1) * f) * a(j); |
---|
72 | c(k) = sum + (a(1) + sign * a(n1)) / 2.0; |
---|
73 | sign = -sign; |
---|
74 | } |
---|
75 | |
---|
76 | for (k=2; k<=n; k++) |
---|
77 | { |
---|
78 | Real sum = 0.0; |
---|
79 | for (int j=2; j<=n; j++) sum += sin((j-1) * (k-1) * f) * a(j); |
---|
80 | s(k) = sum; |
---|
81 | } |
---|
82 | s(1) = s(n1) = 0; |
---|
83 | } |
---|
84 | |
---|
85 | static void test(int n) |
---|
86 | { |
---|
87 | Tracer et("Test FFT"); |
---|
88 | |
---|
89 | ColumnVector A(n), B(n), X, Y; |
---|
90 | for (int i=0; i<n; i++) |
---|
91 | { |
---|
92 | Real f = 6.2831853071795864769*i/n; |
---|
93 | A.element(i) = fabs(sin(7.0*f) + 0.5 * cos(19.0 * f)) + (Real)i/(Real)n; |
---|
94 | B.element(i) = fabs(0.25 * cos(31.0 * f)) + (Real)i/(Real)n; |
---|
95 | } |
---|
96 | FFT(A, B, X, Y); FFTI(X, Y, X, Y); |
---|
97 | X = X - A; Y = Y - B; |
---|
98 | Clean(X,0.000000001); Clean(Y,0.000000001); Print(X); Print(Y); |
---|
99 | } |
---|
100 | |
---|
101 | static void test1(int n) |
---|
102 | { |
---|
103 | Tracer et("Test RealFFT"); |
---|
104 | |
---|
105 | ColumnVector A(n), B(n), X, Y; |
---|
106 | for (int i=0; i<n; i++) |
---|
107 | { |
---|
108 | Real f = 6.2831853071795864769*i/n; |
---|
109 | A.element(i) = fabs(sin(7.0*f) + 0.5 * cos(19.0 * f)) + (Real)i/(Real)n; |
---|
110 | } |
---|
111 | B = 0.0; |
---|
112 | FFT(A, B, X, Y); |
---|
113 | B.CleanUp(); // release some space |
---|
114 | int n2 = n/2+1; |
---|
115 | ColumnVector X1,Y1,X2,Y2; |
---|
116 | RealFFT(A, X1, Y1); |
---|
117 | X2 = X1 - X.Rows(1,n2); Y2 = Y1 - Y.Rows(1,n2); |
---|
118 | Clean(X2,0.000000001); Clean(Y2,0.000000001); Print(X2); Print(Y2); |
---|
119 | X2.CleanUp(); Y2.CleanUp(); // release some more space |
---|
120 | RealFFTI(X1,Y1,B); |
---|
121 | B = A - B; |
---|
122 | Clean(B,0.000000001); Print(B); |
---|
123 | } |
---|
124 | |
---|
125 | static void test2(int n) |
---|
126 | { |
---|
127 | Tracer et("cf FFT and slow FT"); |
---|
128 | |
---|
129 | ColumnVector A(n), B(n), X, Y, X1, Y1; |
---|
130 | for (int i=0; i<n; i++) |
---|
131 | { |
---|
132 | Real f = 6.2831853071795864769*i/n; |
---|
133 | A.element(i) = fabs(sin(7.0*f) - 0.5 * cos(19.0 * f)) + (Real)i/(Real)n; |
---|
134 | B.element(i) = fabs(0.25 * cos(31.0 * f)) - (Real)i/(Real)n; |
---|
135 | } |
---|
136 | FFT(A, B, X, Y); |
---|
137 | SlowFT(A, B, X1, Y1); |
---|
138 | X = X - X1; Y = Y - Y1; |
---|
139 | Clean(X,0.000000001); Clean(Y,0.000000001); Print(X); Print(Y); |
---|
140 | } |
---|
141 | |
---|
142 | static void test3(int n) |
---|
143 | { |
---|
144 | Tracer et("cf slow and fast DCT_II and DST_II"); |
---|
145 | |
---|
146 | ColumnVector A(n), X, Y, X1, Y1; |
---|
147 | for (int i=0; i<n; i++) |
---|
148 | { |
---|
149 | Real f = 6.2831853071795864769*i/n; |
---|
150 | A.element(i) = fabs(sin(7.0*f) - 0.55 * cos(19.0 * f) |
---|
151 | + .73 * sin(6.0 * f)) + (Real)i/(Real)n; |
---|
152 | } |
---|
153 | DCT_II(A, X); DST_II(A, Y); |
---|
154 | SlowDTT_II(A, X1, Y1); |
---|
155 | X -= X1; Y -= Y1; |
---|
156 | Clean(X,0.000000001); Clean(Y,0.000000001); Print(X); Print(Y); |
---|
157 | } |
---|
158 | |
---|
159 | static void test4(int n) |
---|
160 | { |
---|
161 | Tracer et("Test DCT_II"); |
---|
162 | |
---|
163 | ColumnVector A1(n); |
---|
164 | for (int i=0; i<n; i++) |
---|
165 | { |
---|
166 | Real f = 6.2831853071795864769*i/n; |
---|
167 | A1.element(i) = |
---|
168 | fabs(sin(7.0*f) + 0.7588 * cos(19.0 * f) + (Real)i/(Real)n); |
---|
169 | } |
---|
170 | // do DCT II by ordinary FFT |
---|
171 | ColumnVector P(2*n), Q(2*n); |
---|
172 | P = 0.0; Q = 0.0; P.Rows(1,n) = A1; |
---|
173 | FFT(P, Q, P, Q); |
---|
174 | ColumnVector B1(n); |
---|
175 | for (int k=0; k<n; k++) |
---|
176 | { |
---|
177 | Real arg = k * 6.2831853071795864769 / (4 * n); |
---|
178 | B1(k+1) = P(k+1) * cos(arg) + Q(k+1) * sin(arg); |
---|
179 | } |
---|
180 | // use DCT_II routine |
---|
181 | ColumnVector B2; |
---|
182 | DCT_II(A1,B2); |
---|
183 | // test inverse |
---|
184 | ColumnVector A2; |
---|
185 | DCT_II_inverse(B2,A2); |
---|
186 | A1 -= A2; B1 -= B2; |
---|
187 | Clean(A1,0.000000001); Clean(B1,0.000000001); Print(A1); Print(B1); |
---|
188 | } |
---|
189 | |
---|
190 | static void test5(int n) |
---|
191 | { |
---|
192 | Tracer et("Test DST_II"); |
---|
193 | |
---|
194 | ColumnVector A1(n); |
---|
195 | for (int i=0; i<n; i++) |
---|
196 | { |
---|
197 | Real f = 6.2831853071795864769*i/n; |
---|
198 | A1.element(i) = |
---|
199 | fabs(sin(11.0*f) + 0.7588 * cos(19.0 * f) + (Real)i/(Real)n); |
---|
200 | } |
---|
201 | // do DST II by ordinary FFT |
---|
202 | ColumnVector P(2*n), Q(2*n); |
---|
203 | P = 0.0; Q = 0.0; P.Rows(1,n) = A1; |
---|
204 | FFT(P, Q, P, Q); |
---|
205 | ColumnVector B1(n); |
---|
206 | for (int k=1; k<=n; k++) |
---|
207 | { |
---|
208 | Real arg = k * 6.2831853071795864769 / (4 * n); |
---|
209 | B1(k) = P(k+1) * sin(arg) - Q(k+1) * cos(arg); |
---|
210 | } |
---|
211 | // use DST_II routine |
---|
212 | ColumnVector B2; |
---|
213 | DST_II(A1,B2); |
---|
214 | // test inverse |
---|
215 | ColumnVector A2; |
---|
216 | DST_II_inverse(B2,A2); |
---|
217 | A1 -= A2; B1 -= B2; |
---|
218 | Clean(A1,0.000000001); Clean(B1,0.000000001); Print(A1); Print(B1); |
---|
219 | } |
---|
220 | |
---|
221 | static void test6(int n) |
---|
222 | { |
---|
223 | Tracer et("Test DST"); |
---|
224 | |
---|
225 | ColumnVector A1(n+1); |
---|
226 | A1(1) = A1(n+1) = 0; |
---|
227 | for (int i=1; i<n; i++) |
---|
228 | { |
---|
229 | Real f = 6.2831853071795864769*i/n; |
---|
230 | A1.element(i) = |
---|
231 | fabs(sin(11.0*f) + 0.7588 * cos(19.0 * f) + (Real)i/(Real)n); |
---|
232 | } |
---|
233 | // do DST by ordinary FFT |
---|
234 | ColumnVector P(2*n), Q(2*n); P = 0.0; Q = 0.0; P.Rows(1,n+1) = A1; |
---|
235 | FFT(P, Q, P, Q); |
---|
236 | ColumnVector B1 = -Q.Rows(1,n+1); |
---|
237 | // use DST routine |
---|
238 | ColumnVector B2; |
---|
239 | DST(A1,B2); |
---|
240 | // test inverse |
---|
241 | ColumnVector A2; |
---|
242 | DST_inverse(B2,A2); |
---|
243 | A1 -= A2; B1 -= B2; |
---|
244 | Clean(A1,0.000000001); Clean(B1,0.000000001); Print(A1); Print(B1); |
---|
245 | } |
---|
246 | |
---|
247 | |
---|
248 | |
---|
249 | static void test7(int n) |
---|
250 | { |
---|
251 | Tracer et("Test DCT"); |
---|
252 | |
---|
253 | ColumnVector A1(n+1); |
---|
254 | for (int i=0; i<=n; i++) |
---|
255 | { |
---|
256 | Real f = 6.2831853071795864769*i/n; |
---|
257 | A1.element(i) = |
---|
258 | fabs(sin(17.0*f) + 0.6399 * cos(23.0 * f) + 1.32*(Real)i/(Real)n); |
---|
259 | } |
---|
260 | // do DCT by ordinary FFT |
---|
261 | ColumnVector P(2*n), Q(2*n); P = 0.0; Q = 0.0; P.Rows(1,n+1) = A1; |
---|
262 | P(1) /= 2.0; P(n+1) /= 2.0; |
---|
263 | FFT(P, Q, P, Q); |
---|
264 | ColumnVector B1 = P.Rows(1,n+1); |
---|
265 | // use DCT routine |
---|
266 | ColumnVector B2; |
---|
267 | DCT(A1,B2); |
---|
268 | // test inverse |
---|
269 | ColumnVector A2; |
---|
270 | DCT_inverse(B2,A2); |
---|
271 | A1 -= A2; B1 -= B2; |
---|
272 | Clean(A1,0.000000001); Clean(B1,0.000000001); Print(A1); Print(B1); |
---|
273 | } |
---|
274 | |
---|
275 | static void test8(int n) |
---|
276 | { |
---|
277 | Tracer et("cf slow and fast DCT and DST"); |
---|
278 | |
---|
279 | ColumnVector A(n+1), X, Y, X1, Y1; |
---|
280 | for (int i=0; i<=n; i++) |
---|
281 | { |
---|
282 | Real f = 6.2831853071795864769*i/n; |
---|
283 | A.element(i) = fabs(sin(7.0*f) - 0.5 * cos(19.0 * f) + |
---|
284 | 0.3 * (Real)i/(Real)n); |
---|
285 | } |
---|
286 | DCT(A, X); DST(A, Y); |
---|
287 | SlowDTT(A, X1, Y1); |
---|
288 | X -= X1; Y -= Y1; |
---|
289 | Clean(X,0.000000001); Clean(Y,0.000000001); Print(X); Print(Y); |
---|
290 | } |
---|
291 | |
---|
292 | |
---|
293 | |
---|
294 | |
---|
295 | void trymatf() |
---|
296 | { |
---|
297 | Tracer et("Fifteenth test of Matrix package"); |
---|
298 | Tracer::PrintTrace(); |
---|
299 | |
---|
300 | int i; |
---|
301 | ColumnVector A(12), B(12); |
---|
302 | for (i = 1; i <=12; i++) |
---|
303 | { |
---|
304 | Real i1 = i - 1; |
---|
305 | A(i) = .7 |
---|
306 | + .2 * cos(6.2831853071795864769 * 4.0 * i1 / 12) |
---|
307 | + .3 * sin(6.2831853071795864769 * 3.0 * i1 / 12); |
---|
308 | B(i) = .9 |
---|
309 | + .5 * sin(6.2831853071795864769 * 2.0 * i1 / 12) |
---|
310 | + .4 * cos(6.2831853071795864769 * 1.0 * i1 / 12); |
---|
311 | } |
---|
312 | FFT(A, B, A, B); |
---|
313 | A(1) -= 8.4; A(3) -= 3.0; A(5) -= 1.2; A(9) -= 1.2; A(11) += 3.0; |
---|
314 | B(1) -= 10.8; B(2) -= 2.4; B(4) += 1.8; B(10) -= 1.8; B(12) -= 2.4; |
---|
315 | Clean(A,0.000000001); Clean(B,0.000000001); Print(A); Print(B); |
---|
316 | |
---|
317 | |
---|
318 | // test FFT |
---|
319 | test(2048); test(2000); test(27*81); test(2310); test(49*49); |
---|
320 | test(13*13*13); test(43*47); |
---|
321 | test(16*16*3); test(16*16*5); test(16*16*7); |
---|
322 | test(8*8*5); |
---|
323 | |
---|
324 | // test realFFT |
---|
325 | test1(2); test1(98); test1(22); test1(100); |
---|
326 | test1(2048); test1(2000); test1(35*35*2); |
---|
327 | |
---|
328 | // compare FFT and slowFFT |
---|
329 | test2(1); test2(13); test2(12); test2(9); test2(16); test2(30); test2(42); |
---|
330 | test2(24); test2(8); test2(40); test2(48); test2(4); test2(3); test2(5); |
---|
331 | test2(32); test2(2); |
---|
332 | |
---|
333 | // compare DCT_II, DST_II and slow versions |
---|
334 | test3(2); test3(26); test3(32); test3(18); |
---|
335 | |
---|
336 | // test DCT_II and DST_II |
---|
337 | test4(2); test5(2); |
---|
338 | test4(202); test5(202); |
---|
339 | test4(1000); test5(1000); |
---|
340 | |
---|
341 | // test DST and DCT |
---|
342 | test6(2); test7(2); |
---|
343 | test6(274); test7(274); |
---|
344 | test6(1000); test7(1000); |
---|
345 | |
---|
346 | // compare DCT, DST and slow versions |
---|
347 | test8(2); test8(26); test8(32); test8(18); |
---|
348 | |
---|
349 | |
---|
350 | // now do the same thing all over again forcing use of old FFT |
---|
351 | FFT_Controller::OnlyOldFFT = true; |
---|
352 | |
---|
353 | for (i = 1; i <=12; i++) |
---|
354 | { |
---|
355 | Real i1 = i - 1; |
---|
356 | A(i) = .7 |
---|
357 | + .2 * cos(6.2831853071795864769 * 4.0 * i1 / 12) |
---|
358 | + .3 * sin(6.2831853071795864769 * 3.0 * i1 / 12); |
---|
359 | B(i) = .9 |
---|
360 | + .5 * sin(6.2831853071795864769 * 2.0 * i1 / 12) |
---|
361 | + .4 * cos(6.2831853071795864769 * 1.0 * i1 / 12); |
---|
362 | } |
---|
363 | FFT(A, B, A, B); |
---|
364 | A(1) -= 8.4; A(3) -= 3.0; A(5) -= 1.2; A(9) -= 1.2; A(11) += 3.0; |
---|
365 | B(1) -= 10.8; B(2) -= 2.4; B(4) += 1.8; B(10) -= 1.8; B(12) -= 2.4; |
---|
366 | Clean(A,0.000000001); Clean(B,0.000000001); Print(A); Print(B); |
---|
367 | |
---|
368 | |
---|
369 | // test FFT |
---|
370 | test(2048); test(2000); test(27*81); test(2310); test(49*49); |
---|
371 | test(13*13*13); test(43*47); |
---|
372 | test(16*16*3); test(16*16*5); test(16*16*7); |
---|
373 | test(8*8*5); |
---|
374 | |
---|
375 | // test realFFT |
---|
376 | test1(2); test1(98); test1(22); test1(100); |
---|
377 | test1(2048); test1(2000); test1(35*35*2); |
---|
378 | |
---|
379 | // compare FFT and slowFFT |
---|
380 | test2(1); test2(13); test2(12); test2(9); test2(16); test2(30); test2(42); |
---|
381 | test2(24); test2(8); test2(40); test2(48); test2(4); test2(3); test2(5); |
---|
382 | test2(32); test2(2); |
---|
383 | |
---|
384 | // compare DCT_II, DST_II and slow versions |
---|
385 | test3(2); test3(26); test3(32); test3(18); |
---|
386 | |
---|
387 | // test DCT_II and DST_II |
---|
388 | test4(2); test5(2); |
---|
389 | test4(202); test5(202); |
---|
390 | test4(1000); test5(1000); |
---|
391 | |
---|
392 | // test DST and DCT |
---|
393 | test6(2); test7(2); |
---|
394 | test6(274); test7(274); |
---|
395 | test6(1000); test7(1000); |
---|
396 | |
---|
397 | // compare DCT, DST and slow versions |
---|
398 | test8(2); test8(26); test8(32); test8(18); |
---|
399 | |
---|
400 | FFT_Controller::OnlyOldFFT = false; |
---|
401 | |
---|
402 | |
---|
403 | |
---|
404 | } |
---|