00001
00120 #ifndef __SUPPORT_FFT__
00121 #define __SUPPORT_FFT__
00122
00123 #include <errno.h>
00124 #include <stdio.h>
00125
00126 #include <sstream>
00127 #include <string>
00128
00129 #include "fftw3.h"
00130
00131 #include "msg_stream.h"
00132
00133
00134 namespace FFT{
00135
00136
00137
00138
00139
00140
00141
00142
00143
00145 class Support {
00146
00147 public:
00148
00149 typedef unsigned int size_type;
00150
00151 typedef double real_type;
00152 typedef fftw_complex complex_type;
00153
00154 typedef real_type* space_data_type;
00155 typedef complex_type* frequency_data_type;
00156 typedef void* buffer_type;
00157
00158
00161 inline Support(const size_type w,
00162 const size_type h);
00163
00164 inline ~Support();
00165
00166
00168
00169 inline size_type x_space_size() const;
00170 inline size_type y_space_size() const;
00172
00174
00175 inline size_type x_frequency_size() const;
00176 inline size_type y_frequency_size() const;
00178
00180 inline buffer_type create_buffer() const;
00181
00183 inline void destroy_buffer(buffer_type buffer) const;
00184
00185
00186
00187
00189 template <typename Real_data_2D_array>
00190 void save_space_data(Real_data_2D_array* const array) const;
00191
00193 template <typename Real_data_2D_array>
00194 void load_space_data(const Real_data_2D_array& array);
00195
00196
00197
00198
00200 template <typename Complex_data_2D_array>
00201 void save_frequency_data(Complex_data_2D_array* const array) const;
00202
00204 template <typename Complex_data_2D_array>
00205 void load_frequency_data(const Complex_data_2D_array& array);
00206
00207
00208
00209
00211 inline void save_space_data_into_buffer(buffer_type buffer) const;
00212
00214 inline void load_space_data_from_buffer(buffer_type buffer);
00215
00216
00217
00218
00220 inline void save_frequency_data_into_buffer(buffer_type buffer) const;
00221
00223 inline void load_frequency_data_from_buffer(buffer_type buffer);
00224
00225
00226
00227
00229 inline void space_to_frequency();
00230
00232 inline void frequency_to_space();
00233
00234
00235
00236
00239 inline void multiply_frequency_data_by_buffer(buffer_type buffer,
00240 const bool scale = false);
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00253 static inline void set_fftw_flags(const unsigned flags);
00254
00255
00257 static inline void set_wisdom_file(const std::string file_name);
00258
00259
00260 private:
00261
00263
00264 fftw_plan forward, backward;
00266
00268 space_data_type space_data;
00269
00271 frequency_data_type frequency_data;
00272
00274
00275
00276 const size_type width;
00277 const size_type height;
00279
00281
00282
00283 const size_type support_w;
00284 const size_type support_h;
00285 const size_type mem_size;
00287
00288 static inline size_type index(const size_type x,
00289 const size_type y,
00290 const size_type w,
00291 const size_type h);
00292
00293
00294
00295
00296
00297
00298
00300 static unsigned fftw_flags;
00301
00303 static std::string wisdom_file;
00304
00306 static size_type support_number;
00307
00309 static inline void new_support();
00310
00312 static inline void delete_support();
00313 };
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 unsigned Support::fftw_flags = FFTW_EXHAUSTIVE;
00339 std::string Support::wisdom_file = std::string("");
00340 Support::size_type Support::support_number = 0;
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 void Support::set_fftw_flags(const unsigned flags){
00351 fftw_flags = flags;
00352 }
00353
00354 void Support::set_wisdom_file(const std::string file_name){
00355 wisdom_file = file_name;
00356 }
00357
00358
00359
00360 void Support::new_support(){
00361 support_number++;
00362
00363
00364 if ((support_number > 1)||(wisdom_file.size() == 0)){
00365 return;
00366 }
00367
00368
00369
00370
00371
00372
00373 FILE* f = fopen(wisdom_file.c_str(),"r");
00374
00375 if (f != NULL){
00376 if(fftw_import_wisdom_from_file(f) == 0){
00377 Message::warning<<"error while reading FFTW wisdom file \""
00378 <<wisdom_file<<"\""<<Message::done;
00379 }
00380 fclose(f);
00381 }
00382 else if (errno != ENOENT){
00383 Message::warning<<"error while opening (read mode) FFTW wisdom file \""
00384 <<wisdom_file<<"\""<<Message::done;
00385 }
00386
00387 }
00388
00389
00390
00391 void Support::delete_support(){
00392 support_number--;
00393
00394
00395 if ((support_number > 0)||(wisdom_file.size() == 0)){
00396 return;
00397 }
00398
00399
00400
00401
00402 FILE* f = fopen(wisdom_file.c_str(),"w");
00403
00404 if (f != NULL){
00405 fftw_export_wisdom_to_file(f);
00406 fclose(f);
00407 }
00408 else{
00409 Message::warning<<"error while opening (write mode) FFTW wisdom file \""
00410 <<wisdom_file<<"\"\n"
00411 <<"no file saved"<<Message::done;
00412 }
00413 }
00414
00423 Support::Support(const size_type w,
00424 const size_type h):
00425 width(w),
00426 height(h),
00427
00428 support_w(w),
00429 support_h(h/2+1),
00430 mem_size(w*(h/2+1)*sizeof(complex_type)) {
00431
00432 new_support();
00433
00434
00435 space_data = reinterpret_cast<space_data_type>(fftw_malloc(mem_size));
00436
00437
00438 frequency_data = reinterpret_cast<frequency_data_type>(space_data);
00439
00440
00441
00442 forward = fftw_plan_dft_r2c_2d(width,height,
00443 space_data,frequency_data,
00444 fftw_flags);
00445
00446 backward = fftw_plan_dft_c2r_2d(width,height,
00447 frequency_data,space_data,
00448 fftw_flags);
00449 }
00450
00451
00452
00453
00454
00455
00456 Support::~Support(){
00457
00458 delete_support();
00459
00460
00461 fftw_destroy_plan(forward);
00462 fftw_destroy_plan(backward);
00463
00464 fftw_free(space_data);
00465 }
00466
00467
00468
00469
00470 Support::size_type Support::x_space_size() const{
00471 return width;
00472 }
00473
00474
00475
00476 Support::size_type Support::y_space_size() const{
00477 return height;
00478 }
00479
00480
00481 Support::size_type Support::x_frequency_size() const{
00482 return support_w;
00483 }
00484
00485
00486 Support::size_type Support::y_frequency_size() const{
00487 return support_h;
00488 }
00489
00490
00491
00492 Support::size_type Support::index(const size_type x,
00493 const size_type y,
00494 const size_type w,
00495 const size_type h){
00496 return y + x*h;
00497 }
00498
00499
00500
00501
00502 Support::buffer_type Support::create_buffer() const{
00503
00504 return fftw_malloc(mem_size);
00505 }
00506
00507 void Support::destroy_buffer(buffer_type buffer) const{
00508
00509 fftw_free(buffer);
00510 }
00511
00512
00513
00514
00519 template <typename Real_data_2D_array>
00520 void Support::save_space_data(Real_data_2D_array* const array) const{
00521
00522 array->resize(width,height);
00523
00524 for(size_type x=0;x<width;x++){
00525 for(size_type y=0;y<height;y++){
00526 const size_type i = index(x,y,support_w,2*support_h);
00527
00528 (*array)(x,y) = space_data[i];
00529 }
00530 }
00531 }
00532
00537 template <typename Real_data_2D_array>
00538 void Support::load_space_data(const Real_data_2D_array& array){
00539
00540 if ((array.x_size()!=width)||(array.y_size()!=height)){
00541 Message::error<<"Support::load_space_data : size does not match"
00542 <<Message::done;
00543 }
00544
00545 for(size_type x=0;x<width;x++){
00546 for(size_type y=0;y<height;y++){
00547 const size_type i = index(x,y,support_w,2*support_h);
00548
00549 space_data[i] = array(x,y);
00550 }
00551 }
00552
00553 }
00554
00555
00556
00557
00563 template <typename Complex_data_2D_array>
00564 void Support::save_frequency_data(Complex_data_2D_array* const array) const{
00565
00566 typedef typename Complex_data_2D_array::value_type cplx_type;
00567
00568 array->resize(support_w,support_h);
00569
00570 for(size_type x=0;x<support_w;x++){
00571 for(size_type y=0;y<support_h;y++){
00572 const size_type i = index(x,y,support_w,support_h);
00573
00574 (*array)(x,y) = cplx_type(frequency_data[i][0],frequency_data[i][1]);
00575 }
00576 }
00577 }
00578
00585 template <typename Complex_data_2D_array>
00586 void Support::load_frequency_data(const Complex_data_2D_array& array){
00587
00588 if ((array.x_size()!=support_w)||(array.y_size()!=support_h)){
00589 Message::error<<"Support::load_frequency_data : size does not match"
00590 <<Message::done;
00591 }
00592
00593 for(size_type x=0;x<support_w;x++){
00594 for(size_type y=0;y<support_h;y++){
00595 const size_type i = index(x,y,support_w,support_h);
00596
00597 frequency_data[i][0] = array(x,y).real();
00598 frequency_data[i][1] = array(x,y).imag();
00599 }
00600 }
00601
00602 }
00603
00604
00605
00606
00607
00608 void Support::save_space_data_into_buffer(buffer_type buffer) const{
00609 memcpy(buffer,space_data,mem_size);
00610 }
00611
00612 void Support::load_space_data_from_buffer(buffer_type buffer){
00613 memcpy(space_data,buffer,mem_size);
00614 }
00615
00616
00617
00618
00619 void Support::save_frequency_data_into_buffer(buffer_type buffer) const{
00620 memcpy(buffer,frequency_data,mem_size);
00621 }
00622
00623 void Support::load_frequency_data_from_buffer(buffer_type buffer){
00624 memcpy(frequency_data,buffer,mem_size);
00625 }
00626
00627
00628
00629
00630
00631 void Support::space_to_frequency(){
00632 fftw_execute(forward);
00633 }
00634
00635
00636 void Support::frequency_to_space(){
00637 fftw_execute(backward);
00638 }
00639
00640
00641
00642
00643 void Support::multiply_frequency_data_by_buffer(buffer_type buffer,
00644 const bool scale){
00645
00646 const size_type size = support_w*support_h;
00647 const frequency_data_type freq_buffer =
00648 reinterpret_cast<frequency_data_type>(buffer);
00649
00650 const real_type s = scale ? 1.0/(width*height) : 1.0;
00651
00652 for(size_type i=0;i<size;i++){
00653
00654 const double a_re = frequency_data[i][0];
00655 const double a_im = frequency_data[i][1];
00656
00657 const double b_re = freq_buffer[i][0];
00658 const double b_im = freq_buffer[i][1];
00659
00660 frequency_data[i][0] = (a_re*b_re - a_im*b_im)*s;
00661 frequency_data[i][1] = (a_re*b_im + a_im*b_re)*s;
00662
00663 }
00664
00665 }
00666
00667 }
00668
00669
00670 #endif