ei_imklfft_impl.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // This Source Code Form is subject to the terms of the Mozilla
5 // Public License v. 2.0. If a copy of the MPL was not distributed
6 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 
8 #include <mkl_dfti.h>
9 
10 #include "./InternalHeaderCheck.h"
11 
12 #include <complex>
13 #include <memory>
14 
15 namespace Eigen {
16 namespace internal {
17 namespace imklfft {
18 
19 #define RUN_OR_ASSERT(EXPR, ERROR_MSG) \
20  { \
21  MKL_LONG status = (EXPR); \
22  eigen_assert(status == DFTI_NO_ERROR && (ERROR_MSG)); \
23  };
24 
25 inline MKL_Complex16* complex_cast(const std::complex<double>* p) {
26  return const_cast<MKL_Complex16*>(reinterpret_cast<const MKL_Complex16*>(p));
27 }
28 
29 inline MKL_Complex8* complex_cast(const std::complex<float>* p) {
30  return const_cast<MKL_Complex8*>(reinterpret_cast<const MKL_Complex8*>(p));
31 }
32 
33 /*
34  * Parameters:
35  * precision: enum, Precision of the transform: DFTI_SINGLE or DFTI_DOUBLE.
36  * forward_domain: enum, Forward domain of the transform: DFTI_COMPLEX or
37  * DFTI_REAL. dimension: MKL_LONG Dimension of the transform. sizes: MKL_LONG if
38  * dimension = 1.Length of the transform for a one-dimensional transform. sizes:
39  * Array of type MKL_LONG otherwise. Lengths of each dimension for a
40  * multi-dimensional transform.
41  */
42 inline void configure_descriptor(std::shared_ptr<DFTI_DESCRIPTOR>& handl,
43  enum DFTI_CONFIG_VALUE precision,
44  enum DFTI_CONFIG_VALUE forward_domain,
45  MKL_LONG dimension, MKL_LONG* sizes) {
46  eigen_assert(dimension == 1 ||
47  dimension == 2 &&
48  "Transformation dimension must be less than 3.");
49 
50  DFTI_DESCRIPTOR_HANDLE res = nullptr;
51  if (dimension == 1) {
52  RUN_OR_ASSERT(DftiCreateDescriptor(&res, precision, forward_domain,
53  dimension, *sizes),
54  "DftiCreateDescriptor failed.")
55  handl.reset(res, [](DFTI_DESCRIPTOR_HANDLE handle) { DftiFreeDescriptor(&handle); });
56  if (forward_domain == DFTI_REAL) {
57  // Set CCE storage
58  RUN_OR_ASSERT(DftiSetValue(handl.get(), DFTI_CONJUGATE_EVEN_STORAGE,
59  DFTI_COMPLEX_COMPLEX),
60  "DftiSetValue failed.")
61  }
62  } else {
64  DftiCreateDescriptor(&res, precision, DFTI_COMPLEX, dimension, sizes),
65  "DftiCreateDescriptor failed.")
66  handl.reset(res, [](DFTI_DESCRIPTOR_HANDLE handle) { DftiFreeDescriptor(&handle); });
67  }
68 
69  RUN_OR_ASSERT(DftiSetValue(handl.get(), DFTI_PLACEMENT, DFTI_NOT_INPLACE),
70  "DftiSetValue failed.")
71  RUN_OR_ASSERT(DftiCommitDescriptor(handl.get()), "DftiCommitDescriptor failed.")
72 }
73 
74 template <typename T>
75 struct plan {};
76 
77 template <>
78 struct plan<float> {
79  typedef float scalar_type;
80  typedef MKL_Complex8 complex_type;
81 
82  std::shared_ptr<DFTI_DESCRIPTOR> m_plan;
83 
84  plan() = default;
85 
86  enum DFTI_CONFIG_VALUE precision = DFTI_SINGLE;
87 
88  inline void forward(complex_type* dst, complex_type* src, MKL_LONG nfft) {
89  if (m_plan == 0) {
90  configure_descriptor(m_plan, precision, DFTI_COMPLEX, 1, &nfft);
91  }
92  RUN_OR_ASSERT(DftiComputeForward(m_plan.get(), src, dst),
93  "DftiComputeForward failed.")
94  }
95 
96  inline void inverse(complex_type* dst, complex_type* src, MKL_LONG nfft) {
97  if (m_plan == 0) {
98  configure_descriptor(m_plan, precision, DFTI_COMPLEX, 1, &nfft);
99  }
100  RUN_OR_ASSERT(DftiComputeBackward(m_plan.get(), src, dst),
101  "DftiComputeBackward failed.")
102  }
103 
104  inline void forward(complex_type* dst, scalar_type* src, MKL_LONG nfft) {
105  if (m_plan == 0) {
106  configure_descriptor(m_plan, precision, DFTI_REAL, 1, &nfft);
107  }
108  RUN_OR_ASSERT(DftiComputeForward(m_plan.get(), src, dst),
109  "DftiComputeForward failed.")
110  }
111 
112  inline void inverse(scalar_type* dst, complex_type* src, MKL_LONG nfft) {
113  if (m_plan == 0) {
114  configure_descriptor(m_plan, precision, DFTI_REAL, 1, &nfft);
115  }
116  RUN_OR_ASSERT(DftiComputeBackward(m_plan.get(), src, dst),
117  "DftiComputeBackward failed.")
118  }
119 
120  inline void forward2(complex_type* dst, complex_type* src, int n0, int n1) {
121  if (m_plan == 0) {
122  MKL_LONG sizes[2] = {n0, n1};
123  configure_descriptor(m_plan, precision, DFTI_COMPLEX, 2, sizes);
124  }
125  RUN_OR_ASSERT(DftiComputeForward(m_plan.get(), src, dst),
126  "DftiComputeForward failed.")
127  }
128 
129  inline void inverse2(complex_type* dst, complex_type* src, int n0, int n1) {
130  if (m_plan == 0) {
131  MKL_LONG sizes[2] = {n0, n1};
132  configure_descriptor(m_plan, precision, DFTI_COMPLEX, 2, sizes);
133  }
134  RUN_OR_ASSERT(DftiComputeBackward(m_plan.get(), src, dst),
135  "DftiComputeBackward failed.")
136  }
137 };
138 
139 template <>
140 struct plan<double> {
141  typedef double scalar_type;
142  typedef MKL_Complex16 complex_type;
143 
144  std::shared_ptr<DFTI_DESCRIPTOR> m_plan;
145 
146  plan() = default;
147 
148  enum DFTI_CONFIG_VALUE precision = DFTI_DOUBLE;
149 
150  inline void forward(complex_type* dst, complex_type* src, MKL_LONG nfft) {
151  if (m_plan == 0) {
152  configure_descriptor(m_plan, precision, DFTI_COMPLEX, 1, &nfft);
153  }
154  RUN_OR_ASSERT(DftiComputeForward(m_plan.get(), src, dst),
155  "DftiComputeForward failed.")
156  }
157 
158  inline void inverse(complex_type* dst, complex_type* src, MKL_LONG nfft) {
159  if (m_plan == 0) {
160  configure_descriptor(m_plan, precision, DFTI_COMPLEX, 1, &nfft);
161  }
162  RUN_OR_ASSERT(DftiComputeBackward(m_plan.get(), src, dst),
163  "DftiComputeBackward failed.")
164  }
165 
166  inline void forward(complex_type* dst, scalar_type* src, MKL_LONG nfft) {
167  if (m_plan == 0) {
168  configure_descriptor(m_plan, precision, DFTI_REAL, 1, &nfft);
169  }
170  RUN_OR_ASSERT(DftiComputeForward(m_plan.get(), src, dst),
171  "DftiComputeForward failed.")
172  }
173 
174  inline void inverse(scalar_type* dst, complex_type* src, MKL_LONG nfft) {
175  if (m_plan == 0) {
176  configure_descriptor(m_plan, precision, DFTI_REAL, 1, &nfft);
177  }
178  RUN_OR_ASSERT(DftiComputeBackward(m_plan.get(), src, dst),
179  "DftiComputeBackward failed.")
180  }
181 
182  inline void forward2(complex_type* dst, complex_type* src, int n0, int n1) {
183  if (m_plan == 0) {
184  MKL_LONG sizes[2] = {n0, n1};
185  configure_descriptor(m_plan, precision, DFTI_COMPLEX, 2, sizes);
186  }
187  RUN_OR_ASSERT(DftiComputeForward(m_plan.get(), src, dst),
188  "DftiComputeForward failed.")
189  }
190 
191  inline void inverse2(complex_type* dst, complex_type* src, int n0, int n1) {
192  if (m_plan == 0) {
193  MKL_LONG sizes[2] = {n0, n1};
194  configure_descriptor(m_plan, precision, DFTI_COMPLEX, 2, sizes);
195  }
196  RUN_OR_ASSERT(DftiComputeBackward(m_plan.get(), src, dst),
197  "DftiComputeBackward failed.")
198  }
199 };
200 
201 template <typename Scalar_>
202 struct imklfft_impl {
203  typedef Scalar_ Scalar;
204  typedef std::complex<Scalar> Complex;
205 
206  inline void clear() { m_plans.clear(); }
207 
208  // complex-to-complex forward FFT
209  inline void fwd(Complex* dst, const Complex* src, int nfft) {
210  MKL_LONG size = nfft;
211  get_plan(nfft, dst, src)
212  .forward(complex_cast(dst), complex_cast(src), size);
213  }
214 
215  // real-to-complex forward FFT
216  inline void fwd(Complex* dst, const Scalar* src, int nfft) {
217  MKL_LONG size = nfft;
218  get_plan(nfft, dst, src)
219  .forward(complex_cast(dst), const_cast<Scalar*>(src), nfft);
220  }
221 
222  // 2-d complex-to-complex
223  inline void fwd2(Complex* dst, const Complex* src, int n0, int n1) {
224  get_plan(n0, n1, dst, src)
225  .forward2(complex_cast(dst), complex_cast(src), n0, n1);
226  }
227 
228  // inverse complex-to-complex
229  inline void inv(Complex* dst, const Complex* src, int nfft) {
230  MKL_LONG size = nfft;
231  get_plan(nfft, dst, src)
232  .inverse(complex_cast(dst), complex_cast(src), nfft);
233  }
234 
235  // half-complex to scalar
236  inline void inv(Scalar* dst, const Complex* src, int nfft) {
237  MKL_LONG size = nfft;
238  get_plan(nfft, dst, src)
239  .inverse(const_cast<Scalar*>(dst), complex_cast(src), nfft);
240  }
241 
242  // 2-d complex-to-complex
243  inline void inv2(Complex* dst, const Complex* src, int n0, int n1) {
244  get_plan(n0, n1, dst, src)
245  .inverse2(complex_cast(dst), complex_cast(src), n0, n1);
246  }
247 
248  private:
249  std::map<int64_t, plan<Scalar>> m_plans;
250 
251  inline plan<Scalar>& get_plan(int nfft, void* dst,
252  const void* src) {
253  int inplace = dst == src ? 1 : 0;
254  int aligned = ((reinterpret_cast<size_t>(src) & 15) |
255  (reinterpret_cast<size_t>(dst) & 15)) == 0
256  ? 1
257  : 0;
258  int64_t key = ((nfft << 2) | (inplace << 1) | aligned)
259  << 1;
260 
261  // Create element if key does not exist.
262  return m_plans[key];
263  }
264 
265  inline plan<Scalar>& get_plan(int n0, int n1, void* dst,
266  const void* src) {
267  int inplace = (dst == src) ? 1 : 0;
268  int aligned = ((reinterpret_cast<size_t>(src) & 15) |
269  (reinterpret_cast<size_t>(dst) & 15)) == 0
270  ? 1
271  : 0;
272  int64_t key = (((((int64_t)n0) << 31) | (n1 << 2) |
273  (inplace << 1) | aligned)
274  << 1) +
275  1;
276 
277  // Create element if key does not exist.
278  return m_plans[key];
279  }
280 };
281 
282 #undef RUN_OR_ASSERT
283 
284 } // namespace imklfft
285 } // namespace internal
286 } // namespace Eigen
#define eigen_assert(x)
cout<< "Here is the matrix m:"<< endl<< m<< endl;Matrix< ptrdiff_t, 3, 1 > res
float * p
#define RUN_OR_ASSERT(EXPR, ERROR_MSG)
std::int64_t int64_t
: TensorContractionSycl.h, provides various tensor contraction kernel for SYCL backend
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_inverse_op< typename Derived::Scalar >, const Derived > inverse(const Eigen::ArrayBase< Derived > &x)
SparseMat::Index size