| 206 | |
| 207 | template<typename Tc, typename Tr> |
| 208 | Array<Tc> fft_r2c(const Array<Tr> &in, const int rank) { |
| 209 | const dim4 idims = in.dims(); |
| 210 | const dim4 istrides = in.strides(); |
| 211 | Array<Tc> out = createEmptyArray<Tc>( |
| 212 | dim4({idims[0] / 2 + 1, idims[1], idims[2], idims[3]})); |
| 213 | const dim4 ostrides = out.strides(); |
| 214 | |
| 215 | constexpr bool is_single = std::is_same_v<Tr, float>; |
| 216 | constexpr auto precision = (is_single) |
| 217 | ? ::oneapi::mkl::dft::precision::SINGLE |
| 218 | : ::oneapi::mkl::dft::precision::DOUBLE; |
| 219 | using desc_ty = |
| 220 | ::oneapi::mkl::dft::descriptor<precision, |
| 221 | ::oneapi::mkl::dft::domain::REAL>; |
| 222 | |
| 223 | std::vector<std::int64_t> fft_input_strides = |
| 224 | computeStrides(rank, istrides, in.getOffset()); |
| 225 | std::vector<std::int64_t> fft_output_strides = |
| 226 | computeStrides(rank, ostrides, out.getOffset()); |
| 227 | |
| 228 | int batch = 1; |
| 229 | for (int i = rank; i < 4; i++) { batch *= idims[i]; } |
| 230 | |
| 231 | const bool isInPlace = false; |
| 232 | PlanType descP = findPlan<precision, ::oneapi::mkl::dft::domain::REAL>( |
| 233 | rank, isInPlace, idims.get(), fft_input_strides.data(), istrides[rank], |
| 234 | fft_output_strides.data(), ostrides[rank], batch); |
| 235 | |
| 236 | desc_ty *desc = (desc_ty *)descP.get(); |
| 237 | |
| 238 | ::oneapi::mkl::dft::compute_forward(*desc, *in.get(), *out.get()); |
| 239 | |
| 240 | return out; |
| 241 | } |
| 242 | |
| 243 | template<typename Tr, typename Tc> |
| 244 | Array<Tr> fft_c2r(const Array<Tc> &in, const dim4 &odims, const int rank) { |