FftwReal2dDftData.h
Go to the documentation of this file.
1 // FftwReal2dDftData.h
2 //
3 // David Adams
4 // January 2021
5 //
6 // Concrete class that holds the representation of 2D DFT data used in FFTW.
7 //
8 // For real data[i0][i1] with dimensions n0 and n1, the DFT data is stored as
9 // complex values dft[i0][i1] with dimensions n0 and (n1/2 + 1).
10 // The values for i1 > n1/2 may be otained with
11 // dft[i0][i1] = CC{dft[n0-i0][n1-i1]} for i0 > 0
12 // dft[0][i1] = CC{dft[0][n1-i1]}
13 // where CC denotes complex conjugation.
14 
15 #ifndef FftwReal2dDftData_H
16 #define FftwReal2dDftData_H
17 
19 #include "fftw3.h"
20 
21 //**********************************************************************
22 
23 template<typename F> class FftwReal2dDftData;
26 
27 //**********************************************************************
28 
29 template<typename F>
30 class FftwReal2dDftData : public Real2dDftData<F> {
31 
32 public:
33 
34  using typename Real2dDftData<F>::Index;
35  using typename Real2dDftData<F>::IndexArray;
36  using IndexArrayVector = std::vector<IndexArray>;
37  using typename Real2dDftData<F>::Float;
38  using typename Real2dDftData<F>::Complex; // same memory layout as fftw_complex
39  using ComplexVector = std::vector<Complex>;
40  using typename Real2dDftData<F>::Norm;
41 
42  // FFTW DFT data size for specified sample sizes.
43  // Returns the number of complex values.
44  template<std::size_t N>
45  static Index dftComplexDataSize(const std::array<Index, N>& nsams) {
46  Index ndat = 1;
47  Index ndim = nsams.size();
48  for ( Index idim=0; idim<ndim; ++idim ) {
49  Index nsam = nsams[idim];
50  Index fac = idim == ndim - 1 ? nsam/2 + 1 : nsam;
51  ndat *= fac;
52  }
53  return ndat;
54  }
55 
56  // FFTW DFT data size for specified sample sizes.
57  // Returns the number of floats, i.e. twice the number of complex values.
58  template<std::size_t N>
59  static Index dftFloatDataSize(const std::array<Index, N>& nsams) {
60  return 2*dftComplexDataSize(nsams);
61  }
62 
63  // Ctor.
65  : m_norm(norm) {
66  reset(nsams);
67  }
68 
69  // Normalization.
70  Norm normalization() const override { return m_norm; }
71 
72  // The number of dimensions.
73  Index rank() const { return 2; }
74 
75  // Clear data.
76  void clear() override {
77  for ( Index& nsam : m_nsams ) nsam = 0;
78  m_data.clear();
79  }
80 
81  // Reset the DFT data.
82  void reset(const IndexArray& nsams) override {
83  clear();
84  m_nsams = nsams;
85  Index ndat = dftComplexDataSize(nsams);
86  m_data.resize(ndat, 0.0);
87  }
88 
89  // Return the dimensions.
90  const IndexArray& nSamples() const override {
91  return m_nsams;
92  }
93  Index size() const { return m_data.size(); }
94  Index nSamples(Index idim) const {
95  if ( idim > rank() ) return 0;
96  return nSamples()[idim];
97  }
98  Index size(Index idim) const { return nSamples(idim); }
99 
100  // Access the raw data.
101  Complex* data() { return m_data.data(); }
102  const Complex* data() const { return m_data.data(); }
103 
104  // Access the raw data by component: real0, imag0, real1, ...
105  Float* floatData() { return reinterpret_cast<Float*>(m_data.data()); }
106  const Float* floatData() const { return reinterpret_cast<const Float*>(m_data.data()); }
107 
108  // Return the global index for an index array.
109  // Returns the number of global indices if any index is out of range.
110  Index globalIndex(const IndexArray& ifrqs) const {
111  Index ifrq0 = ifrqs[0];
112  Index ifrq1 = ifrqs[1];
113  Index nfrq0 = m_nsams[0];
114  Index nfrq1 = m_nsams[1];
115  Index n1 = nfrq1/2 + 1;
116  if ( ifrq0 >= nfrq0 ) {
117  return size();
118  }
119  if ( ifrq1 >= nfrq1 ) {
120  return size();
121  }
122  if ( ifrq1 >= n1 ) {
123  if ( ifrq0 > 0 ) ifrq0 = nfrq0 - ifrq0;
124  ifrq1 = nfrq1 - ifrq1;
125  }
126  return n1*ifrq0 + ifrq1;
127  }
128 
129  // Return the index arrays for a global index.
130  // Empty if idat is out of range (>= size())
131  // Otherwise returns one or two pairs
133  IndexArrayVector arrs;
134  Index nfrq0 = m_nsams[0];
135  Index nfrq1 = m_nsams[1];
136  Index n1 = nfrq1/2 + 1;
137  Index ifrq0 = idat/n1;
138  if ( ifrq0 >= nfrq0 ) return arrs;
139  Index ifrq1 = idat%n1;
140  arrs.push_back(IndexArray({ifrq0, ifrq1}));
141  Index jfrq0 = ifrq0 > 0 ? nfrq0 - ifrq0 : 0;
142  if ( ifrq1 == 0 ) return arrs;
143  Index jfrq1 = nfrq1 - ifrq1;
144  if ( jfrq1 == ifrq1 ) return arrs;
145  arrs.push_back(IndexArray({jfrq0, jfrq1}));
146  return arrs;
147  }
148 
149  // Return the value for a global index.
150  Complex value(Index idat) const {
151  if ( idat >= size() ) return this->badValue();
152  return m_data[idat];
153  }
154 
155  // Return the value for an index array.
156  // The index arrays are checked first iff pchk != nullptr.
157  // If any of these checks fail or the calculated index is out of range,
158  // badValue() is returned.
159  Complex value(const IndexArray& isams) const override {
160  Index idat = globalIndex(isams);
161  return value(idat);
162  }
163 
164  // Move data in.
165  int moveIn(const IndexArray nsams, ComplexVector& data) {
166  m_nsams = nsams;
167  m_data = std::move(data);
168  return 0;
169  }
170 
171  // Copy data in.
172  int copyIn(const IndexArray nsams, const ComplexVector& data) {
173  m_nsams = nsams;
174  m_data = data;
175  return 0;
176  }
177 
178  // Move data out.
180  data = m_data;
181  clear();
182  return 0;
183  }
184 
185  // Copy the data out.
186  int copyOut(ComplexVector& data) const {
187  data = m_data;
188  return 0;
189  }
190 
191 private:
192 
193  // Data.
197 
198 };
199 
200 //**********************************************************************
201 
202 #endif
std::array< Index, 2 > IndexArray
Definition: Real2dDftData.h:27
const Complex * data() const
void clear() override
Index nSamples(Index idim) const
int copyIn(const IndexArray nsams, const ComplexVector &data)
IndexArrayVector indexArrays(Index idat) const
int moveOut(ComplexVector &data)
Norm normalization() const override
static Index dftComplexDataSize(const std::array< Index, N > &nsams)
ComplexVector m_data
Index rank() const
Index globalIndex(const IndexArray &ifrqs) const
void reset(const IndexArray &nsams) override
def move(depos, offset)
Definition: depos.py:107
int moveIn(const IndexArray nsams, ComplexVector &data)
Complex value(const IndexArray &isams) const override
FftwReal2dDftData(Norm norm, const IndexArray &nsams)
unsigned int Index
Definition: Real2dDftData.h:26
Index size() const
auto norm(Vector const &v)
Return norm of the specified vector.
Complex badValue() const
Definition: Real2dDftData.h:83
std::complex< Float > Complex
Definition: Real2dDftData.h:29
std::vector< Complex > ComplexVector
static Index dftFloatDataSize(const std::array< Index, N > &nsams)
int copyOut(ComplexVector &data) const
Index size(Index idim) const
const IndexArray & nSamples() const override
Complex value(Index idat) const
std::vector< IndexArray > IndexArrayVector
const Float * floatData() const