cstplan.hh
Go to the documentation of this file.
1 /* -*- mia-c++ -*-
2  *
3  * This file is part of MIA - a toolbox for medical image analysis
4  * Copyright (c) Leipzig, Madrid 1999-2017 Gert Wollny
5  *
6  * MIA is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with MIA; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 #include <stdexcept>
23 #include <string>
24 #include <vector>
25 
26 #include <fftw3.h>
27 
28 #include <mia/core/msgstream.hh>
29 
31 
32 
33 template <typename T>
34 class TCSTPlan {
35 public:
36  typedef typename T::value_type value_type;
37 
38  TCSTPlan(fftwf_r2r_kind forward, std::vector<int> size);
39 
40  virtual ~TCSTPlan();
41 
42  template <typename D>
43  void execute(const D& in_data, D& out_data) const;
44 
45  const std::vector<int>& get_size() const;
46 
47 private:
48  mutable value_type *m_in;
49  mutable value_type *m_out;
50 
51  std::vector<int> m_size;
52  float m_scale;
53  size_t m_n;
54 
55  fftwf_plan m_forward_plan;
56  fftwf_plan m_backward_plan;
57 
58  virtual void do_execute(value_type *buffer) const = 0;
59 
60  struct Scale {
61  Scale(float scale): m_scale(scale){
62  }
63  value_type operator ()(const value_type& x) const{
64  return m_scale * x;
65  }
66  float m_scale;
67  };
68 };
69 
70 template <typename T>
71 const std::vector<int>& TCSTPlan<T>::get_size() const
72 {
73  return m_size;
74 }
75 
76 template <typename T>
77 TCSTPlan<T>::TCSTPlan(fftwf_r2r_kind forward, std::vector<int> size):
78  m_size(size),
79  m_scale(1.0)
80 {
81  std::string msg;
82  size_t rank = m_size.size();
83  fftwf_r2r_kind backward;
84 
85 
86  switch (forward) {
87  case FFTW_RODFT00:
88  for (size_t i = 0; i < rank; ++i)
89  m_scale *= 0.5 / ( size[i] + 1.0);
90  break;
91  case FFTW_REDFT00:
92  for (size_t i = 0; i < rank; ++i)
93  m_scale *= 0.5 / ( size[i] - 1.0);
94  break;
95  default:
96  for (size_t i = 0; i < rank; ++i)
97  m_scale *= 0.5 / size[i];
98  break;
99  }
100 
101  switch (forward) {
102  case FFTW_RODFT00:
103  case FFTW_REDFT00:
104  case FFTW_RODFT11:
105  case FFTW_REDFT11:
106  backward = forward;
107  break;
108  case FFTW_RODFT10:
109  backward = FFTW_RODFT01;
110  break;
111  case FFTW_REDFT10:
112  backward = FFTW_REDFT01;
113  break;
114  case FFTW_RODFT01:
115  backward = FFTW_RODFT10;
116  break;
117  case FFTW_REDFT01:
118  backward = FFTW_REDFT10;
119  break;
120  default:
121  throw std::invalid_argument("TCSTPlan: unknown transformtion requested");
122  }
123 
124  std::vector<fftwf_r2r_kind> fw_kind(rank, forward);
125  std::vector<fftwf_r2r_kind> bw_kind(rank, backward);
126 
127 
128  const int howmany = sizeof(value_type)/sizeof(float);
129  cvdebug() << "howmany = " << howmany << "\n";
130  m_n = 1;
131  for (size_t i = 0; i < rank; ++i)
132  m_n *= m_size[i];
133 
134 
135  if (NULL == (m_in = (value_type *) fftwf_malloc(sizeof(T) * m_n))) {
136  msg = "unable to allocate FFTW data";
137  goto in_fail;
138  }
139 
140  if ( NULL == (m_out = (value_type *) fftwf_malloc(sizeof(T) * m_n))) {
141  msg = "unable to allocate FFTW data";
142  goto out_fail;
143  }
144 
145  if (0 == (m_forward_plan = fftwf_plan_many_r2r(rank, &size[0], howmany,
146  m_in, NULL, howmany, 1,
147  m_out, NULL, howmany, 1,
148  &fw_kind[0], FFTW_ESTIMATE))) {
149  msg = "unable to create FFTW forward plan";
150  goto plan_fw_fail;
151  }
152 
153  if (0 == (m_backward_plan = fftwf_plan_many_r2r(rank, &size[0], howmany,
154  m_out, NULL, howmany, 1,
155  m_in, NULL, howmany, 1,
156  &bw_kind[0], FFTW_ESTIMATE))) {
157  msg = "unable to create FFTW backward plan";
158  goto plan_bw_fail;
159  }
160 
161  return;
162 
163  plan_bw_fail:
164  fftwf_destroy_plan(m_forward_plan);
165  plan_fw_fail:
166  fftwf_free(m_out);
167  out_fail:
168  fftwf_free(m_in);
169  in_fail:
170  throw std::runtime_error(msg);
171 }
172 
173 template <typename T>
175 {
176  fftwf_destroy_plan(m_backward_plan);
177  fftwf_destroy_plan(m_forward_plan);
178  fftwf_free(m_out);
179  fftwf_free(m_in);
180 
181 }
182 
183 template <typename T>
184 template <typename D>
185 void TCSTPlan<T>::execute(const D& in_data, D& out_data) const
186 {
187  assert(m_n == in_data.size());
188  assert(m_n == out_data.size());
189 
190  copy(in_data.begin(), in_data.end(), m_in);
191  fftwf_execute( m_forward_plan);
192  do_execute(m_out);
193  fftwf_execute(m_backward_plan);
194  transform( m_in, m_in + m_n, out_data.begin(), Scale(m_scale) );
195 }
196 
CDebugSink & cvdebug()
Definition: msgstream.hh:216
TCSTPlan(fftwf_r2r_kind forward, std::vector< int > size)
Definition: cstplan.hh:77
#define NS_MIA_BEGIN
conveniance define to start the mia namespace
Definition: defines.hh:33
void execute(const D &in_data, D &out_data) const
Definition: cstplan.hh:185
const std::vector< int > & get_size() const
Definition: cstplan.hh:71
T::value_type value_type
Definition: cstplan.hh:36
virtual ~TCSTPlan()
Definition: cstplan.hh:174
#define NS_MIA_END
conveniance define to end the mia namespace
Definition: defines.hh:36