1 /* ************************************************************************
2 * Copyright 2013 Advanced Micro Devices, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 * ************************************************************************/
16
17
18 #include <gtest/gtest.h>
19 #include<math.h>
20
21 #include "test_constants.h"
22 #include "fftw_transform.h"
23 #include "cl_transform.h"
24 #include "buffer.h"
25 #include "typedefs.h"
26 #include <stdexcept>
27 #include <vector>
28
29 namespace placeness
30 {
31 enum placeness_t { in_place = CLFFT_INPLACE, out_of_place = CLFFT_OUTOFPLACE };
32 }
33
34 enum data_pattern { impulse, sawtooth, value, erratic };
35
36 namespace direction
37 {
38 enum direction_t { forward, backward };
39 }
40
41 clfftResultLocation cl_placeness( placeness::placeness_t placeness );
42 clfftLayout cl_layout( layout::buffer_layout_t layout_in );
43
44
45 /*****************************************************/
46 /*****************************************************/
47 // dimension is inferred from lengths.size()
48 // tightly packed is inferred from strides.empty()
49 template< class T, class cl_T, class fftw_T >
50 void complex_to_complex( data_pattern pattern, direction::direction_t direction,
51 std::vector<size_t> lengths, size_t batch,
52 std::vector<size_t> input_strides, std::vector<size_t> output_strides,
53 size_t input_distance, size_t output_distance,
54 layout::buffer_layout_t in_layout, layout::buffer_layout_t out_layout,
55 placeness::placeness_t placeness,
56 T scale = 1.0f )
57 {
58 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
59 input_strides.empty() ? NULL : &input_strides[0],
60 output_strides.empty() ? NULL : &output_strides[0],
61 batch, input_distance, output_distance,
62 cl_layout(in_layout), cl_layout(out_layout),
63 cl_placeness(placeness) );
64
65 fftw<T, fftw_T> reference( lengths.size(), &lengths[0], batch, c2c );
66
67 if( pattern == sawtooth )
68 {
69 test_fft.set_input_to_sawtooth( 1.0f );
70 reference.set_data_to_sawtooth( 1.0f );
71 }
72 else if( pattern == value )
73 {
74 test_fft.set_input_to_value( 2.0f, 2.5f );
75 reference.set_all_data_to_value( 2.0f, 2.5f );
76 }
77 else if( pattern == impulse )
78 {
79 test_fft.set_input_to_impulse();
80 reference.set_data_to_impulse();
81 }
82 else if( pattern == erratic )
83 {
84 test_fft.set_input_to_random();
85 reference.set_data_to_random();
86 }
87 else
88 {
89 throw std::runtime_error( "invalid pattern type in complex_to_complex()" );
90 }
91
92 // if we're starting with unequal data, we're destined for failure
93 EXPECT_EQ( true, test_fft.input_buffer() == reference.input_buffer() );
94
95 if( direction == direction::forward )
96 {
97 test_fft.set_forward_transform();
98 test_fft.forward_scale( scale );
99
100 reference.set_forward_transform();
101 reference.forward_scale( scale );
102 }
103 else if( direction == direction::backward )
104 {
105 test_fft.set_backward_transform();
106 test_fft.backward_scale( scale );
107
108 reference.set_backward_transform();
109 reference.backward_scale( scale );
110 }
111 else
112 throw std::runtime_error( "invalid direction in complex_to_complex()" );
113 reference.transform();
114 test_fft.transform();
115
116 EXPECT_EQ( true, test_fft.result() == reference.result() );
117 }
118
119 /*****************************************************/
120 /*****************************************************/
121 // complex to complex transform with precallback
122 // dimension is inferred from lengths.size()
123 // tightly packed is inferred from strides.empty()
124 template< class T, class cl_T, class fftw_T >
125 void precallback_complex_to_complex( data_pattern pattern, direction::direction_t direction,
126 std::vector<size_t> lengths, size_t batch,
127 std::vector<size_t> input_strides, std::vector<size_t> output_strides,
128 size_t input_distance, size_t output_distance,
129 layout::buffer_layout_t in_layout, layout::buffer_layout_t out_layout,
130 placeness::placeness_t placeness, T scale = 1.0f, bool hasUserDatatype = false )
131 {
132 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
133 input_strides.empty() ? NULL : &input_strides[0],
134 output_strides.empty() ? NULL : &output_strides[0],
135 batch, input_distance, output_distance,
136 cl_layout(in_layout), cl_layout(out_layout),
137 cl_placeness(placeness) );
138
139 fftw<T, fftw_T> reference( lengths.size(), &lengths[0], batch, c2c );
140
141 //initialize input
142 if( pattern == sawtooth )
143 {
144 test_fft.set_input_to_sawtooth( 1.0f );
145 reference.set_data_to_sawtooth( 1.0f );
146 }
147 else if( pattern == value )
148 {
149 test_fft.set_input_to_value( 2.0f, 2.5f );
150 reference.set_all_data_to_value( 2.0f, 2.5f );
151 }
152 else if( pattern == impulse )
153 {
154 test_fft.set_input_to_impulse();
155 reference.set_data_to_impulse();
156 }
157 else if( pattern == erratic )
158 {
159 test_fft.set_input_to_random();
160 reference.set_data_to_random();
161 }
162 else
163 {
164 throw std::runtime_error( "invalid pattern type in complex_to_complex()" );
165 }
166
167 // if we're starting with unequal data, we're destined for failure
168 EXPECT_EQ( true, test_fft.input_buffer() == reference.input_buffer() );
169
170 //set precallback values
171 if (hasUserDatatype)
172 {
173 test_fft.set_input_precallback_userdatatype();
174 }
175 else
176 {
177 test_fft.set_input_precallback();
178 }
179 reference.set_input_precallback();
180
181 if( direction == direction::forward )
182 {
183 test_fft.set_forward_transform();
184 test_fft.forward_scale( scale );
185
186 reference.set_forward_transform();
187 reference.forward_scale( scale );
188 }
189 else if( direction == direction::backward )
190 {
191 test_fft.set_backward_transform();
192 test_fft.backward_scale( scale );
193
194 reference.set_backward_transform();
195 reference.backward_scale( scale );
196 }
197 else
198 throw std::runtime_error( "invalid direction in complex_to_complex()" );
199
200 reference.transform();
201 test_fft.transform();
202
203 EXPECT_EQ( true, test_fft.result() == reference.result() );
204 }
205
206 /*****************************************************/
207 /*****************************************************/
208 // complex to complex transform with postcallback
209 // dimension is inferred from lengths.size()
210 // tightly packed is inferred from strides.empty()
211 template< class T, class cl_T, class fftw_T >
212 void postcallback_complex_to_complex( data_pattern pattern, direction::direction_t direction,
213 std::vector<size_t> lengths, size_t batch,
214 std::vector<size_t> input_strides, std::vector<size_t> output_strides,
215 size_t input_distance, size_t output_distance,
216 layout::buffer_layout_t in_layout, layout::buffer_layout_t out_layout,
217 placeness::placeness_t placeness, T scale = 1.0f, bool hasUserDatatype = false )
218 {
219 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
220 input_strides.empty() ? NULL : &input_strides[0],
221 output_strides.empty() ? NULL : &output_strides[0],
222 batch, input_distance, output_distance,
223 cl_layout(in_layout), cl_layout(out_layout),
224 cl_placeness(placeness) );
225
226 fftw<T, fftw_T> reference( lengths.size(), &lengths[0], batch, c2c );
227
228 //initialize input
229 if( pattern == sawtooth )
230 {
231 test_fft.set_input_to_sawtooth( 1.0f );
232 reference.set_data_to_sawtooth( 1.0f );
233 }
234 else if( pattern == value )
235 {
236 test_fft.set_input_to_value( 2.0f, 2.5f );
237 reference.set_all_data_to_value( 2.0f, 2.5f );
238 }
239 else if( pattern == impulse )
240 {
241 test_fft.set_input_to_impulse();
242 reference.set_data_to_impulse();
243 }
244 else if( pattern == erratic )
245 {
246 test_fft.set_input_to_random();
247 reference.set_data_to_random();
248 }
249 else
250 {
251 throw std::runtime_error( "invalid pattern type in complex_to_complex()" );
252 }
253
254 // if we're starting with unequal data, we're destined for failure
255 EXPECT_EQ( true, test_fft.input_buffer() == reference.input_buffer() );
256
257 //set postcallback values
258 if (hasUserDatatype)
259 {
260 //test_fft.set_input_precallback_userdatatype();
261 }
262 else
263 {
264 test_fft.set_output_postcallback();
265 }
266
267 if( direction == direction::forward )
268 {
269 test_fft.set_forward_transform();
270 test_fft.forward_scale( scale );
271
272 reference.set_forward_transform();
273 reference.forward_scale( scale );
274 }
275 else if( direction == direction::backward )
276 {
277 test_fft.set_backward_transform();
278 test_fft.backward_scale( scale );
279
280 reference.set_backward_transform();
281 reference.backward_scale( scale );
282 }
283 else
284 throw std::runtime_error( "invalid direction in complex_to_complex()" );
285
286 reference.transform();
287 test_fft.transform();
288
289 reference.set_output_postcallback();
290
291 EXPECT_EQ( true, test_fft.result() == reference.result() );
292 }
293
294 /*****************************************************/
295 /*****************************************************/
296 // complex to complex transform with pre and post callback
297 // dimension is inferred from lengths.size()
298 // tightly packed is inferred from strides.empty()
299 template< class T, class cl_T, class fftw_T >
300 void pre_and_post_callback_complex_to_complex( data_pattern pattern, direction::direction_t direction,
301 std::vector<size_t> lengths, size_t batch,
302 std::vector<size_t> input_strides, std::vector<size_t> output_strides,
303 size_t input_distance, size_t output_distance,
304 layout::buffer_layout_t in_layout, layout::buffer_layout_t out_layout,
305 placeness::placeness_t placeness, T scale = 1.0f, bool withLDS = false)
306 {
307 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
308 input_strides.empty() ? NULL : &input_strides[0],
309 output_strides.empty() ? NULL : &output_strides[0],
310 batch, input_distance, output_distance,
311 cl_layout(in_layout), cl_layout(out_layout),
312 cl_placeness(placeness) );
313
314 fftw<T, fftw_T> reference( lengths.size(), &lengths[0], batch, c2c );
315
316 //initialize input
317 if( pattern == sawtooth )
318 {
319 test_fft.set_input_to_sawtooth( 1.0f );
320 reference.set_data_to_sawtooth( 1.0f );
321 }
322 else if( pattern == value )
323 {
324 test_fft.set_input_to_value( 2.0f, 2.5f );
325 reference.set_all_data_to_value( 2.0f, 2.5f );
326 }
327 else if( pattern == impulse )
328 {
329 test_fft.set_input_to_impulse();
330 reference.set_data_to_impulse();
331 }
332 else if( pattern == erratic )
333 {
334 test_fft.set_input_to_random();
335 reference.set_data_to_random();
336 }
337 else
338 {
339 throw std::runtime_error( "invalid pattern type in complex_to_complex()" );
340 }
341
342 // if we're starting with unequal data, we're destined for failure
343 EXPECT_EQ( true, test_fft.input_buffer() == reference.input_buffer() );
344
345 //set callback values
346 if (withLDS)
347 {
348 unsigned int localMemSize = 64 * sizeof(T);
349 test_fft.set_input_precallback(localMemSize);
350 reference.set_input_precallback_special();
351
352 test_fft.set_output_postcallback(localMemSize);
353 }
354 else
355 {
356 test_fft.set_input_precallback();
357 reference.set_input_precallback();
358
359 //set postcallback values
360 test_fft.set_output_postcallback();
361 }
362
363 if( direction == direction::forward )
364 {
365 test_fft.set_forward_transform();
366 test_fft.forward_scale( scale );
367
368 reference.set_forward_transform();
369 reference.forward_scale( scale );
370 }
371 else if( direction == direction::backward )
372 {
373 test_fft.set_backward_transform();
374 test_fft.backward_scale( scale );
375
376 reference.set_backward_transform();
377 reference.backward_scale( scale );
378 }
379 else
380 throw std::runtime_error( "invalid direction in complex_to_complex()" );
381
382 reference.transform();
383 test_fft.transform();
384
385 //update reference for postcallback
386 if (withLDS)
387 {
388 reference.set_output_postcallback_special();
389 }
390 else
391 {
392 reference.set_output_postcallback();
393 }
394
395 EXPECT_EQ( true, test_fft.result() == reference.result() );
396 }
397
398 /*****************************************************/
399 /*****************************************************/
400 // complex to complex transform with precallback function that uses LDS
401 template< class T, class cl_T, class fftw_T >
402 void precallback_complex_to_complex_lds( data_pattern pattern, direction::direction_t direction,
403 std::vector<size_t> lengths, size_t batch,
404 std::vector<size_t> input_strides, std::vector<size_t> output_strides,
405 size_t input_distance, size_t output_distance,
406 layout::buffer_layout_t in_layout, layout::buffer_layout_t out_layout,
407 placeness::placeness_t placeness,
408 T scale = 1.0f )
409 {
410 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
411 input_strides.empty() ? NULL : &input_strides[0],
412 output_strides.empty() ? NULL : &output_strides[0],
413 batch, input_distance, output_distance,
414 cl_layout(in_layout), cl_layout(out_layout),
415 cl_placeness(placeness) );
416
417 fftw<T, fftw_T> reference( lengths.size(), &lengths[0], batch, c2c );
418
419 //initialize input
420 if( pattern == sawtooth )
421 {
422 test_fft.set_input_to_sawtooth( 1.0f );
423 reference.set_data_to_sawtooth( 1.0f );
424 }
425 else if( pattern == value )
426 {
427 test_fft.set_input_to_value( 2.0f, 2.5f );
428 reference.set_all_data_to_value( 2.0f, 2.5f );
429 }
430 else if( pattern == impulse )
431 {
432 test_fft.set_input_to_impulse();
433 reference.set_data_to_impulse();
434 }
435 else if( pattern == erratic )
436 {
437 test_fft.set_input_to_random();
438 reference.set_data_to_random();
439 }
440 else
441 {
442 throw std::runtime_error( "invalid pattern type in complex_to_complex()" );
443 }
444
445 // if we're starting with unequal data, we're destined for failure
446 EXPECT_EQ( true, test_fft.input_buffer() == reference.input_buffer() );
447
448 //set precallback values
449 //Test assumes 64 length data
450 unsigned int localMemSize = 64 * sizeof(T);
451 test_fft.set_input_precallback(localMemSize);
452 reference.set_input_precallback_special();
453
454 if( direction == direction::forward )
455 {
456 test_fft.set_forward_transform();
457 test_fft.forward_scale( scale );
458
459 reference.set_forward_transform();
460 reference.forward_scale( scale );
461 }
462 else if( direction == direction::backward )
463 {
464 test_fft.set_backward_transform();
465 test_fft.backward_scale( scale );
466
467 reference.set_backward_transform();
468 reference.backward_scale( scale );
469 }
470 else
471 throw std::runtime_error( "invalid direction in complex_to_complex()" );
472
473 reference.transform();
474 test_fft.transform();
475
476 EXPECT_EQ( true, test_fft.result() == reference.result() );
477 }
478
479 /*****************************************************/
480 /*****************************************************/
481 // complex to complex transform with postcallback function that uses LDS
482 template< class T, class cl_T, class fftw_T >
483 void postcallback_complex_to_complex_lds( data_pattern pattern, direction::direction_t direction,
484 std::vector<size_t> lengths, size_t batch,
485 std::vector<size_t> input_strides, std::vector<size_t> output_strides,
486 size_t input_distance, size_t output_distance,
487 layout::buffer_layout_t in_layout, layout::buffer_layout_t out_layout,
488 placeness::placeness_t placeness, T scale = 1.0f )
489 {
490 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
491 input_strides.empty() ? NULL : &input_strides[0],
492 output_strides.empty() ? NULL : &output_strides[0],
493 batch, input_distance, output_distance,
494 cl_layout(in_layout), cl_layout(out_layout),
495 cl_placeness(placeness) );
496
497 fftw<T, fftw_T> reference( lengths.size(), &lengths[0], batch, c2c );
498
499 //initialize input
500 if( pattern == sawtooth )
501 {
502 test_fft.set_input_to_sawtooth( 1.0f );
503 reference.set_data_to_sawtooth( 1.0f );
504 }
505 else if( pattern == value )
506 {
507 test_fft.set_input_to_value( 2.0f, 2.5f );
508 reference.set_all_data_to_value( 2.0f, 2.5f );
509 }
510 else if( pattern == impulse )
511 {
512 test_fft.set_input_to_impulse();
513 reference.set_data_to_impulse();
514 }
515 else if( pattern == erratic )
516 {
517 test_fft.set_input_to_random();
518 reference.set_data_to_random();
519 }
520 else
521 {
522 throw std::runtime_error( "invalid pattern type in complex_to_complex()" );
523 }
524
525 // if we're starting with unequal data, we're destined for failure
526 EXPECT_EQ( true, test_fft.input_buffer() == reference.input_buffer() );
527
528 //set postcallback values
529 //Test assumes 64 length data
530 unsigned int localMemSize = 64 * sizeof(T);
531 test_fft.set_output_postcallback(localMemSize);
532
533 if( direction == direction::forward )
534 {
535 test_fft.set_forward_transform();
536 test_fft.forward_scale( scale );
537
538 reference.set_forward_transform();
539 reference.forward_scale( scale );
540 }
541 else if( direction == direction::backward )
542 {
543 test_fft.set_backward_transform();
544 test_fft.backward_scale( scale );
545
546 reference.set_backward_transform();
547 reference.backward_scale( scale );
548 }
549 else
550 throw std::runtime_error( "invalid direction in complex_to_complex()" );
551
552 reference.transform();
553 test_fft.transform();
554
555 reference.set_output_postcallback_special();
556
557 EXPECT_EQ( true, test_fft.result() == reference.result() );
558 }
559
560 /*****************************************************/
561 /*****************************************************/
562 // dimension is inferred from lengths.size()
563 // tightly packed is inferred from strides.empty()
564 // input layout is always real
565 template< class T, class cl_T, class fftw_T >
566 void real_to_complex( data_pattern pattern,
567 std::vector<size_t> lengths, size_t batch,
568 std::vector<size_t> input_strides, std::vector<size_t> output_strides,
569 size_t input_distance, size_t output_distance,
570 layout::buffer_layout_t out_layout,
571 placeness::placeness_t placeness,
572 T scale = 1.0f )
573 {
574 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
575 input_strides.empty() ? NULL : &input_strides[0],
576 output_strides.empty() ? NULL : &output_strides[0],
577 batch, input_distance, output_distance,
578 cl_layout(layout::real), cl_layout(out_layout),
579 cl_placeness(placeness) );
580
581 fftw<T, fftw_T> reference( lengths.size(), &lengths[0], batch, r2c );
582
583 if( pattern == sawtooth )
584 {
585 test_fft.set_input_to_sawtooth( 1.0f );
586 reference.set_data_to_sawtooth( 1.0f );
587 }
588 else if( pattern == value )
589 {
590 test_fft.set_input_to_value( 2.0f );
591 reference.set_all_data_to_value( 2.0f );
592 }
593 else if( pattern == impulse )
594 {
595 test_fft.set_input_to_impulse();
596 reference.set_data_to_impulse();
597 }
598 else if( pattern == erratic )
599 {
600 test_fft.set_input_to_random();
601 reference.set_data_to_random();
602 }
603 else
604 {
605 throw std::runtime_error( "invalid pattern type in real_to_complex()" );
606 }
607
608 // if we're starting with unequal data, we're destined for failure
609 EXPECT_EQ( true, test_fft.input_buffer() == reference.input_buffer() );
610
611 test_fft.forward_scale( scale );
612 reference.forward_scale( scale );
613
614 test_fft.transform();
615 reference.transform();
616
617 EXPECT_EQ( true, test_fft.result() == reference.result() );
618 }
619
620 /*****************************************************/
621 /*****************************************************/
622 // dimension is inferred from lengths.size()
623 // tightly packed is inferred from strides.empty()
624 // input layout is always real
625 template< class T, class cl_T, class fftw_T >
626 void precallback_real_to_complex( data_pattern pattern,
627 std::vector<size_t> lengths, size_t batch,
628 std::vector<size_t> input_strides, std::vector<size_t> output_strides,
629 size_t input_distance, size_t output_distance,
630 layout::buffer_layout_t out_layout,
631 placeness::placeness_t placeness,
632 T scale = 1.0f )
633 {
634 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
635 input_strides.empty() ? NULL : &input_strides[0],
636 output_strides.empty() ? NULL : &output_strides[0],
637 batch, input_distance, output_distance,
638 cl_layout(layout::real), cl_layout(out_layout),
639 cl_placeness(placeness) );
640
641 fftw<T, fftw_T> reference( lengths.size(), &lengths[0], batch, r2c );
642
643 if( pattern == sawtooth )
644 {
645 test_fft.set_input_to_sawtooth( 1.0f );
646 reference.set_data_to_sawtooth( 1.0f );
647 }
648 else if( pattern == value )
649 {
650 test_fft.set_input_to_value( 2.0f );
651 reference.set_all_data_to_value( 2.0f );
652 }
653 else if( pattern == impulse )
654 {
655 test_fft.set_input_to_impulse();
656 reference.set_data_to_impulse();
657 }
658 else if( pattern == erratic )
659 {
660 test_fft.set_input_to_random();
661 reference.set_data_to_random();
662 }
663 else
664 {
665 throw std::runtime_error( "invalid pattern type in real_to_complex()" );
666 }
667
668 // if we're starting with unequal data, we're destined for failure
669 EXPECT_EQ( true, test_fft.input_buffer() == reference.input_buffer() );
670
671 test_fft.set_input_precallback();
672 reference.set_input_precallback();
673
674 test_fft.forward_scale( scale );
675 reference.forward_scale( scale );
676
677 test_fft.transform();
678 reference.transform();
679
680 EXPECT_EQ( true, test_fft.result() == reference.result() );
681 }
682
683 /*****************************************************/
684 /*****************************************************/
685 // dimension is inferred from lengths.size()
686 // tightly packed is inferred from strides.empty()
687 // input layout is always real
688 template< class T, class cl_T, class fftw_T >
689 void postcallback_real_to_complex( data_pattern pattern,
690 std::vector<size_t> lengths, size_t batch,
691 std::vector<size_t> input_strides, std::vector<size_t> output_strides,
692 size_t input_distance, size_t output_distance,
693 layout::buffer_layout_t out_layout,
694 placeness::placeness_t placeness,
695 T scale = 1.0f )
696 {
697 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
698 input_strides.empty() ? NULL : &input_strides[0],
699 output_strides.empty() ? NULL : &output_strides[0],
700 batch, input_distance, output_distance,
701 cl_layout(layout::real), cl_layout(out_layout),
702 cl_placeness(placeness) );
703
704 fftw<T, fftw_T> reference( lengths.size(), &lengths[0], batch, r2c );
705
706 if( pattern == sawtooth )
707 {
708 test_fft.set_input_to_sawtooth( 1.0f );
709 reference.set_data_to_sawtooth( 1.0f );
710 }
711 else if( pattern == value )
712 {
713 test_fft.set_input_to_value( 2.0f );
714 reference.set_all_data_to_value( 2.0f );
715 }
716 else if( pattern == impulse )
717 {
718 test_fft.set_input_to_impulse();
719 reference.set_data_to_impulse();
720 }
721 else if( pattern == erratic )
722 {
723 test_fft.set_input_to_random();
724 reference.set_data_to_random();
725 }
726 else
727 {
728 throw std::runtime_error( "invalid pattern type in real_to_complex()" );
729 }
730
731 // if we're starting with unequal data, we're destined for failure
732 EXPECT_EQ( true, test_fft.input_buffer() == reference.input_buffer() );
733
734 test_fft.forward_scale( scale );
735 reference.forward_scale( scale );
736
737 //set postcallback values
738 test_fft.set_output_postcallback();
739
740 test_fft.transform();
741 reference.transform();
742
743 reference.set_output_postcallback();
744
745 EXPECT_EQ( true, test_fft.result() == reference.result() );
746 }
747
748 /*****************************************************/
749 /*****************************************************/
750 // dimension is inferred from lengths.size()
751 // tightly packed is inferred from strides.empty()
752 // output layout is always real
753 template< class T, class cl_T, class fftw_T >
754 void complex_to_real( data_pattern pattern,
755 std::vector<size_t> lengths, size_t batch,
756 std::vector<size_t> input_strides, std::vector<size_t> output_strides,
757 size_t input_distance, size_t output_distance,
758 layout::buffer_layout_t in_layout,
759 placeness::placeness_t placeness,
760 T scale = 1.0f )
761 {
762 fftw<T, fftw_T> data_maker( lengths.size(), &lengths[0], batch, r2c );
763
764 if( pattern == sawtooth )
765 {
766 data_maker.set_data_to_sawtooth(1.0f);
767 }
768 else if( pattern == value )
769 {
770 data_maker.set_all_data_to_value(2.0f);
771 }
772 else if( pattern == impulse )
773 {
774 data_maker.set_data_to_impulse();
775 }
776 else if( pattern == erratic )
777 {
778 data_maker.set_data_to_random();
779 }
780 else
781 {
782 throw std::runtime_error( "invalid pattern type in complex_to_real()" );
783 }
784
785 data_maker.transform();
786
787 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
788 input_strides.empty() ? NULL : &input_strides[0],
789 output_strides.empty() ? NULL : &output_strides[0],
790 batch, input_distance, output_distance,
791 cl_layout(in_layout), cl_layout(layout::real),
792 cl_placeness(placeness) );
793 test_fft.set_input_to_buffer( data_maker.result() );
794
795 fftw<T, fftw_T> reference( lengths.size(), &lengths[0], batch, c2r );
796 reference.set_input_to_buffer(data_maker.result());
797
798 // if we're starting with unequal data, we're destined for failure
799 EXPECT_EQ( true, test_fft.input_buffer() == reference.input_buffer() );
800
801 test_fft.backward_scale( scale );
802 reference.backward_scale( scale );
803
804 test_fft.transform();
805 reference.transform();
806
807 EXPECT_EQ( true, test_fft.result() == reference.result() );
808 }
809
810 /*****************************************************/
811 /*****************************************************/
812 // dimension is inferred from lengths.size()
813 // tightly packed is inferred from strides.empty()
814 // output layout is always real
815 template< class T, class cl_T, class fftw_T >
816 void precallback_complex_to_real( data_pattern pattern,
817 std::vector<size_t> lengths, size_t batch,
818 std::vector<size_t> input_strides, std::vector<size_t> output_strides,
819 size_t input_distance, size_t output_distance,
820 layout::buffer_layout_t in_layout,
821 placeness::placeness_t placeness,
822 T scale = 1.0f )
823 {
824 fftw<T, fftw_T> data_maker( lengths.size(), &lengths[0], batch, r2c );
825
826 if( pattern == sawtooth )
827 {
828 data_maker.set_data_to_sawtooth(1.0f);
829 }
830 else if( pattern == value )
831 {
832 data_maker.set_all_data_to_value(2.0f);
833 }
834 else if( pattern == impulse )
835 {
836 data_maker.set_data_to_impulse();
837 }
838 else if( pattern == erratic )
839 {
840 data_maker.set_data_to_random();
841 }
842 else
843 {
844 throw std::runtime_error( "invalid pattern type in complex_to_real()" );
845 }
846
847 data_maker.transform();
848
849 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
850 input_strides.empty() ? NULL : &input_strides[0],
851 output_strides.empty() ? NULL : &output_strides[0],
852 batch, input_distance, output_distance,
853 cl_layout(in_layout), cl_layout(layout::real),
854 cl_placeness(placeness) );
855 test_fft.set_input_to_buffer( data_maker.result() );
856
857 fftw<T, fftw_T> reference( lengths.size(), &lengths[0], batch, c2r );
858 reference.set_input_to_buffer(data_maker.result());
859
860 // if we're starting with unequal data, we're destined for failure
861 EXPECT_EQ( true, test_fft.input_buffer() == reference.input_buffer() );
862
863 test_fft.set_input_precallback();
864 reference.set_input_precallback();
865
866 test_fft.backward_scale( scale );
867 reference.backward_scale( scale );
868
869 test_fft.transform();
870 reference.transform();
871
872 EXPECT_EQ( true, test_fft.result() == reference.result() );
873 }
874
875 template< class T, class cl_T, class fftw_T >
876 void postcallback_complex_to_real( data_pattern pattern,
877 std::vector<size_t> lengths, size_t batch,
878 std::vector<size_t> input_strides, std::vector<size_t> output_strides,
879 size_t input_distance, size_t output_distance,
880 layout::buffer_layout_t in_layout,
881 placeness::placeness_t placeness,
882 T scale = 1.0f )
883 {
884 fftw<T, fftw_T> data_maker( lengths.size(), &lengths[0], batch, r2c );
885
886 if( pattern == sawtooth )
887 {
888 data_maker.set_data_to_sawtooth(1.0f);
889 }
890 else if( pattern == value )
891 {
892 data_maker.set_all_data_to_value(2.0f);
893 }
894 else if( pattern == impulse )
895 {
896 data_maker.set_data_to_impulse();
897 }
898 else if( pattern == erratic )
899 {
900 data_maker.set_data_to_random();
901 }
902 else
903 {
904 throw std::runtime_error( "invalid pattern type in complex_to_real()" );
905 }
906
907 data_maker.transform();
908
909 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
910 input_strides.empty() ? NULL : &input_strides[0],
911 output_strides.empty() ? NULL : &output_strides[0],
912 batch, input_distance, output_distance,
913 cl_layout(in_layout), cl_layout(layout::real),
914 cl_placeness(placeness) );
915 test_fft.set_input_to_buffer( data_maker.result() );
916
917 fftw<T, fftw_T> reference( lengths.size(), &lengths[0], batch, c2r );
918 reference.set_input_to_buffer(data_maker.result());
919
920 // if we're starting with unequal data, we're destined for failure
921 EXPECT_EQ( true, test_fft.input_buffer() == reference.input_buffer() );
922
923 test_fft.backward_scale( scale );
924 reference.backward_scale( scale );
925
926 //set postcallback values
927 test_fft.set_output_postcallback();
928
929 test_fft.transform();
930 reference.transform();
931
932 reference.set_output_postcallback();
933
934 EXPECT_EQ( true, test_fft.result() == reference.result() );
935 }
936
937 /*****************************************************/
938 /*****************************************************/
939 // dimension is inferred from lengths.size()
940 // tightly packed is inferred from strides.empty()
941
942 // no need to support non-unit strides and distances here
943 // they are covered in plenty of other places
944 // and just needlessly complicate things in this case
945 template< class T, class cl_T, class fftw_T >
complex_to_complex_round_trip(data_pattern pattern,std::vector<size_t> lengths,size_t batch,layout::buffer_layout_t layout)946 void complex_to_complex_round_trip( data_pattern pattern,
947 std::vector<size_t> lengths, size_t batch,
948 layout::buffer_layout_t layout )
949 {
950 placeness::placeness_t placeness = placeness::in_place;
951
952 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
953 NULL, NULL, batch, 0, 0,
954 cl_layout(layout), cl_layout(layout),
955 cl_placeness( placeness ) );
956
957 buffer<T> expected( lengths.size(), &lengths[0], NULL, batch, 0, layout, CLFFT_OUTOFPLACE );
958
959 if( pattern == sawtooth )
960 {
961 test_fft.set_input_to_sawtooth( 1.0f );
962 expected.set_all_to_sawtooth( 1.0f );
963 }
964 else if( pattern == value )
965 {
966 test_fft.set_input_to_value( 2.0f, 2.5f );
967 expected.set_all_to_value( 2.0f, 2.5f );
968 }
969 else if( pattern == impulse )
970 {
971 test_fft.set_input_to_impulse();
972 expected.set_all_to_impulse();
973 }
974 else if( pattern == erratic )
975 {
976 test_fft.set_input_to_random();
977 expected.set_all_to_random_data( 10, super_duper_global_seed );
978 }
979 else
980 {
981 throw std::runtime_error( "invalid pattern type in complex_to_complex_round_trip()" );
982 }
983
984 // if we're starting with unequal data, we're destined for failure
985 EXPECT_EQ( true, test_fft.input_buffer() == expected );
986
987 test_fft.set_forward_transform();
988 test_fft.transform();
989
990 // confirm that we actually did something
991 bool stash_suppress_output = suppress_output;
992 suppress_output = true;
993 EXPECT_EQ( false, test_fft.result() == expected );
994 suppress_output = stash_suppress_output;
995
996 test_fft.set_backward_transform();
997 test_fft.transform();
998
999 EXPECT_EQ( true, test_fft.result() == expected );
1000 }
1001
1002 /*****************************************************/
1003 /*****************************************************/
1004 // dimension is inferred from lengths.size()
1005 // tightly packed is inferred from strides.empty()
1006 // no need to support non-unit strides and distances here
1007 // they are covered in plenty of other places
1008 // and just needlessly complicate things in this case
1009 template< class T, class cl_T, class fftw_T >
precallback_complex_to_complex_round_trip(data_pattern pattern,std::vector<size_t> lengths,size_t batch,layout::buffer_layout_t layout)1010 void precallback_complex_to_complex_round_trip( data_pattern pattern,
1011 std::vector<size_t> lengths, size_t batch,
1012 layout::buffer_layout_t layout )
1013 {
1014 placeness::placeness_t placeness = placeness::in_place;
1015
1016 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
1017 NULL, NULL, batch, 0, 0,
1018 cl_layout(layout), cl_layout(layout),
1019 cl_placeness( placeness ) );
1020
1021 buffer<T> expected( lengths.size(), &lengths[0], NULL, batch, 0, layout, CLFFT_OUTOFPLACE );
1022
1023 if( pattern == sawtooth )
1024 {
1025 test_fft.set_input_to_sawtooth( 1.0f );
1026 expected.set_all_to_sawtooth( 1.0f );
1027 }
1028 else if( pattern == value )
1029 {
1030 test_fft.set_input_to_value( 2.0f, 2.5f );
1031 expected.set_all_to_value( 2.0f, 2.5f );
1032 }
1033 else if( pattern == impulse )
1034 {
1035 test_fft.set_input_to_impulse();
1036 expected.set_all_to_impulse();
1037 }
1038 else if( pattern == erratic )
1039 {
1040 test_fft.set_input_to_random();
1041 expected.set_all_to_random_data( 10, super_duper_global_seed );
1042 }
1043 else
1044 {
1045 throw std::runtime_error( "invalid pattern type in complex_to_complex_round_trip()" );
1046 }
1047
1048 // if we're starting with unequal data, we're destined for failure
1049 EXPECT_EQ( true, test_fft.input_buffer() == expected );
1050
1051 test_fft.set_input_precallback();
1052
1053 //precallback user data
1054 buffer<T> userdata( lengths.size(), &lengths[0], NULL, batch, 0, layout::real, CLFFT_OUTOFPLACE);
1055 userdata.set_all_to_random_data(lengths[0], 10);
1056
1057 expected *= userdata;
1058
1059 test_fft.set_forward_transform();
1060 test_fft.transform();
1061
1062 // confirm that we actually did something
1063 bool stash_suppress_output = suppress_output;
1064 suppress_output = true;
1065 EXPECT_EQ( false, test_fft.result() == expected );
1066 suppress_output = stash_suppress_output;
1067
1068 test_fft.refresh_plan();
1069
1070 test_fft.set_backward_transform();
1071 test_fft.transform();
1072
1073 EXPECT_EQ( true, test_fft.result() == expected );
1074 }
1075
1076 /*****************************************************/
1077 /*****************************************************/
1078 // dimension is inferred from lengths.size()
1079 // tightly packed is inferred from strides.empty()
1080 template< class T, class cl_T, class fftw_T >
real_to_complex_round_trip(data_pattern pattern,std::vector<size_t> lengths,size_t batch)1081 void real_to_complex_round_trip( data_pattern pattern,
1082 std::vector<size_t> lengths, size_t batch )
1083 {
1084 placeness::placeness_t placeness = placeness::in_place;
1085
1086 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
1087 NULL, NULL, batch, 0, 0,
1088 cl_layout(layout::real), cl_layout(layout::hermitian_interleaved),
1089 cl_placeness( placeness ) );
1090
1091 buffer<T> expected( lengths.size(), &lengths[0], NULL, batch, 0, layout::real, CLFFT_OUTOFPLACE );
1092
1093 if( pattern == sawtooth )
1094 {
1095 test_fft.set_input_to_sawtooth( 1.0f );
1096 expected.set_all_to_sawtooth( 1.0f );
1097 }
1098 else if( pattern == value )
1099 {
1100 test_fft.set_input_to_value( 2.0f );
1101 expected.set_all_to_value( 2.0f );
1102 }
1103 else if( pattern == impulse )
1104 {
1105 test_fft.set_input_to_impulse();
1106 expected.set_all_to_impulse();
1107 }
1108 else if( pattern == erratic )
1109 {
1110 test_fft.set_input_to_random();
1111 expected.set_all_to_random_data( 10, super_duper_global_seed );
1112 }
1113 else
1114 {
1115 throw std::runtime_error( "invalid pattern type in real_to_complex_round_trip()" );
1116 }
1117
1118 // if we're starting with unequal data, we're destined for failure
1119 EXPECT_EQ( true, test_fft.input_buffer() == expected );
1120
1121 test_fft.transform();
1122
1123 // confirm that we actually did something
1124 bool stash_suppress_output = suppress_output;
1125 suppress_output = true;
1126 EXPECT_EQ( false, test_fft.result() == expected );
1127 suppress_output = stash_suppress_output;
1128
1129 test_fft.swap_layouts();
1130 test_fft.transform();
1131
1132 EXPECT_EQ( true, test_fft.result() == expected );
1133 }
1134
1135 /*****************************************************/
1136 /*****************************************************/
1137 // dimension is inferred from lengths.size()
1138 // tightly packed is inferred from strides.empty()
1139 template< class T, class cl_T, class fftw_T >
precallback_real_to_complex_round_trip(data_pattern pattern,std::vector<size_t> lengths,size_t batch)1140 void precallback_real_to_complex_round_trip( data_pattern pattern,
1141 std::vector<size_t> lengths, size_t batch )
1142 {
1143 placeness::placeness_t placeness = placeness::in_place;
1144
1145 clfft<T, cl_T> test_fft( static_cast<clfftDim>(lengths.size()), &lengths[0],
1146 NULL, NULL, batch, 0, 0,
1147 cl_layout(layout::real), cl_layout(layout::hermitian_interleaved),
1148 cl_placeness( placeness ) );
1149
1150 buffer<T> expected( lengths.size(), &lengths[0], NULL, batch, 0, layout::real, CLFFT_OUTOFPLACE );
1151
1152 if( pattern == sawtooth )
1153 {
1154 test_fft.set_input_to_sawtooth( 1.0f );
1155 expected.set_all_to_sawtooth( 1.0f );
1156 }
1157 else if( pattern == value )
1158 {
1159 test_fft.set_input_to_value( 2.0f );
1160 expected.set_all_to_value( 2.0f );
1161 }
1162 else if( pattern == impulse )
1163 {
1164 test_fft.set_input_to_impulse();
1165 expected.set_all_to_impulse();
1166 }
1167 else if( pattern == erratic )
1168 {
1169 test_fft.set_input_to_random();
1170 expected.set_all_to_random_data( 10, super_duper_global_seed );
1171 }
1172 else
1173 {
1174 throw std::runtime_error( "invalid pattern type in real_to_complex_round_trip()" );
1175 }
1176
1177 // if we're starting with unequal data, we're destined for failure
1178 EXPECT_EQ( true, test_fft.input_buffer() == expected );
1179
1180 test_fft.set_input_precallback();
1181
1182 //precallback user data
1183 buffer<T> userdata( lengths.size(), &lengths[0], NULL, batch, 0, layout::real, CLFFT_OUTOFPLACE);
1184 userdata.set_all_to_random_data(lengths[0], 10);
1185
1186 expected *= userdata;
1187
1188 test_fft.transform();
1189
1190 // confirm that we actually did something
1191 bool stash_suppress_output = suppress_output;
1192 suppress_output = true;
1193 EXPECT_EQ( false, test_fft.result() == expected );
1194 suppress_output = stash_suppress_output;
1195
1196 test_fft.swap_layouts();
1197 test_fft.transform();
1198
1199 EXPECT_EQ( true, test_fft.result() == expected );
1200 }
1201