pypocketfft.cc 13 KB
Newer Older
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
1
2
3
4
5
6
/*
 * This file is part of pocketfft.
 * Licensed under a 3-clause BSD style license - see LICENSE.md
 */

/*
7
 *  Python interface.
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
8
 *
9
 *  Copyright (C) 2019 Max-Planck-Society
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
10
11
12
 *  \author Martin Reinecke
 */

Martin Reinecke's avatar
Martin Reinecke committed
13
14
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
Martin Reinecke's avatar
more  
Martin Reinecke committed
15
#include <pybind11/stl.h>
Martin Reinecke's avatar
Martin Reinecke committed
16

17
#pragma GCC visibility push(hidden)
Martin Reinecke's avatar
Martin Reinecke committed
18

19
#include "pocketfft_hdronly.h"
Martin Reinecke's avatar
Martin Reinecke committed
20

Martin Reinecke's avatar
Martin Reinecke committed
21
//
22
// Python interface
Martin Reinecke's avatar
Martin Reinecke committed
23
24
//

25
namespace {
26

27
28
using namespace std;
using namespace pocketfft;
Martin Reinecke's avatar
Martin Reinecke committed
29

Martin Reinecke's avatar
Martin Reinecke committed
30
31
namespace py = pybind11;

Martin Reinecke's avatar
Martin Reinecke committed
32
33
auto c64 = py::dtype("complex64");
auto c128 = py::dtype("complex128");
Martin Reinecke's avatar
Martin Reinecke committed
34
35
auto f32 = py::dtype("float32");
auto f64 = py::dtype("float64");
Martin Reinecke's avatar
Martin Reinecke committed
36

Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
37
38
39
40
41
42
43
44
45
46
bool tcheck(const py::array &arr, const py::object &t1, const py::object &t2)
  {
  if (arr.dtype().is(t1))
    return true;
  if (arr.dtype().is(t2))
    return false;
  throw runtime_error("unsupported data type");
  }

shape_t copy_shape(const py::array &arr)
Martin Reinecke's avatar
Martin Reinecke committed
47
  {
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
48
  shape_t res(arr.ndim());
Martin Reinecke's avatar
Martin Reinecke committed
49
50
51
52
  for (size_t i=0; i<res.size(); ++i)
    res[i] = arr.shape(i);
  return res;
  }
Martin Reinecke's avatar
Martin Reinecke committed
53

Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
54
stride_t copy_strides(const py::array &arr)
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
55
  {
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
56
  stride_t res(arr.ndim());
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
57
  for (size_t i=0; i<res.size(); ++i)
Martin Reinecke's avatar
Martin Reinecke committed
58
    res[i] = arr.strides(i);
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
59
60
  return res;
  }
Martin Reinecke's avatar
Martin Reinecke committed
61

Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
62
shape_t makeaxes(const py::array &in, py::object axes)
Martin Reinecke's avatar
more  
Martin Reinecke committed
63
  {
Martin Reinecke's avatar
Martin Reinecke committed
64
  if (axes.is(py::none()))
Martin Reinecke's avatar
more  
Martin Reinecke committed
65
    {
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
66
    shape_t res(in.ndim());
Martin Reinecke's avatar
Martin Reinecke committed
67
68
69
    for (size_t i=0; i<res.size(); ++i)
      res[i]=i;
    return res;
Martin Reinecke's avatar
more  
Martin Reinecke committed
70
    }
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
71
  auto tmp=axes.cast<shape_t>();
Martin Reinecke's avatar
fix  
Martin Reinecke committed
72
  if ((tmp.size()>size_t(in.ndim())) || (tmp.size()==0))
Martin Reinecke's avatar
more  
Martin Reinecke committed
73
    throw runtime_error("bad axes argument");
Martin Reinecke's avatar
Martin Reinecke committed
74
75
  for (auto sz: tmp)
    if (sz>=size_t(in.ndim()))
Martin Reinecke's avatar
more  
Martin Reinecke committed
76
      throw runtime_error("invalid axis number");
Martin Reinecke's avatar
Martin Reinecke committed
77
  return tmp;
Martin Reinecke's avatar
more  
Martin Reinecke committed
78
79
  }

Martin Reinecke's avatar
Martin Reinecke committed
80
template<typename T> py::array xfftn_internal(const py::array &in,
81
  const shape_t &axes, double fct, bool inplace, bool fwd)
Martin Reinecke's avatar
Martin Reinecke committed
82
  {
Martin Reinecke's avatar
Martin Reinecke committed
83
  auto dims(copy_shape(in));
84
  py::array res = inplace ? in : py::array_t<complex<T>>(dims);
Martin Reinecke's avatar
sync  
Martin Reinecke committed
85
86
87
  c2c(dims, copy_strides(in), copy_strides(res), axes, fwd,
    reinterpret_cast<const complex<T> *>(in.data()),
    reinterpret_cast<complex<T> *>(res.mutable_data()), T(fct));
Martin Reinecke's avatar
Martin Reinecke committed
88
89
  return res;
  }
Martin Reinecke's avatar
Martin Reinecke committed
90

91
92
py::array xfftn(const py::array &a, py::object axes, double fct, bool inplace,
  bool fwd)
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
93
  {
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
94
  return tcheck(a, c128, c64) ?
95
96
    xfftn_internal<double>(a, makeaxes(a, axes), fct, inplace, fwd) :
    xfftn_internal<float> (a, makeaxes(a, axes), fct, inplace, fwd);
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
97
  }
98
99
100
101
py::array fftn(const py::array &a, py::object axes, double fct, bool inplace)
  { return xfftn(a, axes, fct, inplace, true); }
py::array ifftn(const py::array &a, py::object axes, double fct, bool inplace)
  { return xfftn(a, axes, fct, inplace, false); }
Martin Reinecke's avatar
Martin Reinecke committed
102

Martin Reinecke's avatar
Martin Reinecke committed
103
104
template<typename T> py::array rfftn_internal(const py::array &in,
  py::object axes_, T fct)
Martin Reinecke's avatar
Martin Reinecke committed
105
  {
Martin Reinecke's avatar
Martin Reinecke committed
106
  auto axes = makeaxes(in, axes_);
Martin Reinecke's avatar
Martin Reinecke committed
107
  auto dims_in(copy_shape(in)), dims_out(dims_in);
Martin Reinecke's avatar
more  
Martin Reinecke committed
108
  dims_out[axes.back()] = (dims_out[axes.back()]>>1)+1;
Martin Reinecke's avatar
Martin Reinecke committed
109
  py::array res = py::array_t<complex<T>>(dims_out);
Martin Reinecke's avatar
sync  
Martin Reinecke committed
110
111
112
  r2c(dims_in, copy_strides(in), copy_strides(res), axes,
    reinterpret_cast<const T *>(in.data()),
    reinterpret_cast<complex<T> *>(res.mutable_data()), T(fct));
Martin Reinecke's avatar
more  
Martin Reinecke committed
113
114
  return res;
  }
Martin Reinecke's avatar
Martin Reinecke committed
115
116
py::array rfftn(const py::array &in, py::object axes_, double fct)
  {
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
117
118
  return tcheck(in, f64, f32) ? rfftn_internal<double>(in, axes_, fct)
                              : rfftn_internal<float> (in, axes_, fct);
Martin Reinecke's avatar
Martin Reinecke committed
119
  }
120
template<typename T> py::array xrfft_scipy(const py::array &in,
Martin Reinecke's avatar
Martin Reinecke committed
121
  size_t axis, double fct, bool inplace, bool fwd)
122
123
124
  {
  auto dims(copy_shape(in));
  py::array res = inplace ? in : py::array_t<T>(dims);
Martin Reinecke's avatar
Martin Reinecke committed
125
  r2r_fftpack(dims, copy_strides(in), copy_strides(res), axis, fwd,
Martin Reinecke's avatar
sync  
Martin Reinecke committed
126
127
    reinterpret_cast<const T *>(in.data()),
    reinterpret_cast<T *>(res.mutable_data()), T(fct));
128
129
  return res;
  }
Martin Reinecke's avatar
Martin Reinecke committed
130
py::array rfft_scipy(const py::array &in, size_t axis, double fct, bool inplace)
131
132
133
134
135
  {
  return tcheck(in, f64, f32) ?
    xrfft_scipy<double>(in, axis, fct, inplace, true) :
    xrfft_scipy<float> (in, axis, fct, inplace, true);
  }
Martin Reinecke's avatar
Martin Reinecke committed
136
137
py::array irfft_scipy(const py::array &in, size_t axis, double fct,
  bool inplace)
138
139
140
141
142
  {
  return tcheck(in, f64, f32) ?
    xrfft_scipy<double>(in, axis, fct, inplace, false) :
    xrfft_scipy<float> (in, axis, fct, inplace, false);
  }
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
143
144
template<typename T> py::array irfftn_internal(const py::array &in,
  py::object axes_, size_t lastsize, T fct)
Martin Reinecke's avatar
more  
Martin Reinecke committed
145
  {
Martin Reinecke's avatar
Martin Reinecke committed
146
  auto axes = makeaxes(in, axes_);
Martin Reinecke's avatar
more  
Martin Reinecke committed
147
  size_t axis = axes.back();
Martin Reinecke's avatar
Martin Reinecke committed
148
149
150
  shape_t dims_in(copy_shape(in)), dims_out=dims_in;
  if (lastsize==0) lastsize=2*dims_in[axis]-1;
  if ((lastsize/2) + 1 != dims_in[axis])
Martin Reinecke's avatar
more  
Martin Reinecke committed
151
152
    throw runtime_error("bad lastsize");
  dims_out[axis] = lastsize;
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
153
  py::array res = py::array_t<T>(dims_out);
Martin Reinecke's avatar
bug fix  
Martin Reinecke committed
154
  c2r(dims_out, copy_strides(in), copy_strides(res), axes,
Martin Reinecke's avatar
sync  
Martin Reinecke committed
155
156
    reinterpret_cast<const complex<T> *>(in.data()),
    reinterpret_cast<T *>(res.mutable_data()), T(fct));
Martin Reinecke's avatar
more  
Martin Reinecke committed
157
158
  return res;
  }
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
159
160
161
py::array irfftn(const py::array &in, py::object axes_, size_t lastsize,
  double fct)
  {
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
162
163
164
  return tcheck(in, c128, c64) ?
    irfftn_internal<double>(in, axes_, lastsize, fct) :
    irfftn_internal<float> (in, axes_, lastsize, fct);
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
165
  }
Martin Reinecke's avatar
Martin Reinecke committed
166
167

template<typename T> py::array hartley_internal(const py::array &in,
168
  py::object axes_, double fct, bool inplace)
Martin Reinecke's avatar
more  
Martin Reinecke committed
169
  {
Martin Reinecke's avatar
Martin Reinecke committed
170
  auto dims(copy_shape(in));
171
  py::array res = inplace ? in : py::array_t<T>(dims);
Martin Reinecke's avatar
Martin Reinecke committed
172
  r2r_hartley(dims, copy_strides(in), copy_strides(res), makeaxes(in, axes_),
Martin Reinecke's avatar
sync  
Martin Reinecke committed
173
174
    reinterpret_cast<const T *>(in.data()),
    reinterpret_cast<T *>(res.mutable_data()), T(fct));
Martin Reinecke's avatar
Martin Reinecke committed
175
176
  return res;
  }
177
178
py::array hartley(const py::array &in, py::object axes_, double fct,
  bool inplace)
Martin Reinecke's avatar
Martin Reinecke committed
179
  {
180
181
182
  return tcheck(in, f64, f32) ?
    hartley_internal<double>(in, axes_, fct, inplace) :
    hartley_internal<float> (in, axes_, fct, inplace);
Martin Reinecke's avatar
Martin Reinecke committed
183
  }
184

Martin Reinecke's avatar
fixes  
Martin Reinecke committed
185
template<typename T>py::array complex2hartley(const py::array &in,
Martin Reinecke's avatar
Martin Reinecke committed
186
  const py::array &tmp, py::object axes_, bool inplace)
Martin Reinecke's avatar
fixes  
Martin Reinecke committed
187
  {
Martin Reinecke's avatar
Martin Reinecke committed
188
  using namespace pocketfft::detail;
Martin Reinecke's avatar
fixes  
Martin Reinecke committed
189
  int ndim = in.ndim();
Martin Reinecke's avatar
Martin Reinecke committed
190
  auto dims_out(copy_shape(in));
Martin Reinecke's avatar
Martin Reinecke committed
191
192
193
  py::array out = inplace ? in : py::array_t<T>(dims_out);
  ndarr<cmplx<T>> atmp(tmp.data(), copy_shape(tmp), copy_strides(tmp));
  ndarr<T> aout(out.mutable_data(), copy_shape(out), copy_strides(out));
Martin Reinecke's avatar
fixes  
Martin Reinecke committed
194
  auto axes = makeaxes(in, axes_);
Martin Reinecke's avatar
Martin Reinecke committed
195
  size_t axis = axes.back();
Martin Reinecke's avatar
Martin Reinecke committed
196
197
  multi_iter<1,cmplx<T>,T> it(atmp, aout, axis);
  vector<bool> swp(ndim,false);
Martin Reinecke's avatar
fixes  
Martin Reinecke committed
198
199
  for (auto i: axes)
    if (i!=axis)
Martin Reinecke's avatar
Martin Reinecke committed
200
      swp[i] = true;
Martin Reinecke's avatar
Martin Reinecke committed
201
  while(it.remaining()>0)
Martin Reinecke's avatar
fixes  
Martin Reinecke committed
202
    {
Martin Reinecke's avatar
Martin Reinecke committed
203
    ptrdiff_t rofs = 0;
Martin Reinecke's avatar
Martin Reinecke committed
204
    for (size_t i=0; i<it.pos.size(); ++i)
Martin Reinecke's avatar
fixes  
Martin Reinecke committed
205
      {
Martin Reinecke's avatar
Martin Reinecke committed
206
      if (i==axis) continue;
Martin Reinecke's avatar
fixes  
Martin Reinecke committed
207
      if (!swp[i])
Martin Reinecke's avatar
Martin Reinecke committed
208
        rofs += it.pos[i]*it.oarr.stride(i);
Martin Reinecke's avatar
fixes  
Martin Reinecke committed
209
210
      else
        {
Martin Reinecke's avatar
Martin Reinecke committed
211
212
        auto x = (it.pos[i]==0) ? 0 : it.iarr.shape(i)-it.pos[i];
        rofs += x*it.oarr.stride(i);
Martin Reinecke's avatar
fixes  
Martin Reinecke committed
213
214
        }
      }
Martin Reinecke's avatar
Martin Reinecke committed
215
    it.advance(1);
Martin Reinecke's avatar
Martin Reinecke committed
216
    for (size_t i=0; i<it.length_in(); ++i)
Martin Reinecke's avatar
fixes  
Martin Reinecke committed
217
      {
Martin Reinecke's avatar
Martin Reinecke committed
218
219
      auto re = it.in(i).r;
      auto im = it.in(i).i;
Martin Reinecke's avatar
Martin Reinecke committed
220
      auto rev_i = (i==0) ? 0 : it.length_out()-i;
Martin Reinecke's avatar
Martin Reinecke committed
221
222
      it.out(i) = re+im;
      aout[rofs + rev_i*it.stride_out()] = re-im;
Martin Reinecke's avatar
fixes  
Martin Reinecke committed
223
224
225
226
      }
    }
  return out;
  }
227
py::array mycomplex2hartley(const py::array &in,
Martin Reinecke's avatar
Martin Reinecke committed
228
  const py::array &tmp, py::object axes_, bool inplace)
229
  {
Martin Reinecke's avatar
Martin Reinecke committed
230
231
  return tcheck(in, f64, f32) ? complex2hartley<double>(in, tmp, axes_, inplace)
                              : complex2hartley<float> (in, tmp, axes_, inplace);
232
  }
Martin Reinecke's avatar
Martin Reinecke committed
233
234
235
py::array hartley2(const py::array &in, py::object axes_, double fct,
  bool inplace)
  { return mycomplex2hartley(in, rfftn(in, axes_, fct), axes_, inplace); }
Martin Reinecke's avatar
fixes  
Martin Reinecke committed
236

Martin Reinecke's avatar
Martin Reinecke committed
237
const char *pypocketfft_DS = R"DELIM(Fast Fourier and Hartley transforms.
Martin Reinecke's avatar
Martin Reinecke committed
238
239
240
241
242
243
244
245
246
247
248

This module supports
- single and double precision
- complex and real-valued transforms
- multi-dimensional transforms

For two- and higher-dimensional transforms the code will use SSE2 and AVX
vector instructions for faster execution if these are supported by the CPU and
were enabled during compilation.
)DELIM";

249
250
251
252
253
254
255
256
const char *fftn_DS = R"DELIM(
Performs a forward complex FFT.

Parameters
----------
a : numpy.ndarray (np.complex64 or np.complex128)
    The input data
axes : list of integers
257
    The axes along which the FFT is carried out.
258
    If not set, all axes will be transformed.
Martin Reinecke's avatar
Martin Reinecke committed
259
fct : float
Martin Reinecke's avatar
Martin Reinecke committed
260
    Normalization factor
261
inplace : bool
Martin Reinecke's avatar
Martin Reinecke committed
262
    if False, returns the result in a new array and leaves the input unchanged.
263
    if True, stores the result in the input array and returns a handle to it.
264
265
266
267

Returns
-------
np.ndarray (same shape and data type as a)
268
    The transformed data.
269
270
)DELIM";

Martin Reinecke's avatar
Martin Reinecke committed
271
const char *ifftn_DS = R"DELIM(Performs a backward complex FFT.
272
273
274
275
276
277

Parameters
----------
a : numpy.ndarray (np.complex64 or np.complex128)
    The input data
axes : list of integers
278
    The axes along which the FFT is carried out.
279
    If not set, all axes will be transformed.
Martin Reinecke's avatar
Martin Reinecke committed
280
fct : float
Martin Reinecke's avatar
Martin Reinecke committed
281
    Normalization factor
282
inplace : bool
Martin Reinecke's avatar
Martin Reinecke committed
283
    if False, returns the result in a new array and leaves the input unchanged.
284
    if True, stores the result in the input array and returns a handle to it.
285
286
287
288

Returns
-------
np.ndarray (same shape and data type as a)
Martin Reinecke's avatar
Martin Reinecke committed
289
    The transformed data
290
291
)DELIM";

Martin Reinecke's avatar
Martin Reinecke committed
292
const char *rfftn_DS = R"DELIM(Performs a forward real-valued FFT.
Martin Reinecke's avatar
Martin Reinecke committed
293
294
295
296
297
298

Parameters
----------
a : numpy.ndarray (np.float32 or np.float64)
    The input data
axes : list of integers
299
    The axes along which the FFT is carried out.
Martin Reinecke's avatar
Martin Reinecke committed
300
301
    If not set, all axes will be transformed in ascending order.
fct : float
Martin Reinecke's avatar
Martin Reinecke committed
302
    Normalization factor
Martin Reinecke's avatar
Martin Reinecke committed
303
304
305
306

Returns
-------
np.ndarray (np.complex64 or np.complex128)
Martin Reinecke's avatar
Martin Reinecke committed
307
    The transformed data. The shape is identical to that of the input array,
Martin Reinecke's avatar
Martin Reinecke committed
308
309
310
311
    except for the axis that was transformed last. If the length of that axis
    was n on input, it is n//2+1 on output.
)DELIM";

312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
const char *rfft_scipy_DS = R"DELIM(Performs a forward real-valued FFT.

Parameters
----------
a : numpy.ndarray (np.float32 or np.float64)
    The input data
axis : int
    The axis along which the FFT is carried out.
fct : float
    Normalization factor
inplace : bool
    if False, returns the result in a new array and leaves the input unchanged.
    if True, stores the result in the input array and returns a handle to it.

Returns
-------
np.ndarray (np.float32 or np.float64)
    The transformed data. The shape is identical to that of the input array.
    Along the transformed axis, values are arranged in
    FFTPACK half-complex order, i.e. `a[0].re, a[1].re, a[1].im, a[2].re ...`.
)DELIM";

Martin Reinecke's avatar
Martin Reinecke committed
334
const char *irfftn_DS = R"DELIM(Performs a backward real-valued FFT.
Martin Reinecke's avatar
Martin Reinecke committed
335
336
337
338
339
340

Parameters
----------
a : numpy.ndarray (np.complex64 or np.complex128)
    The input data
axes : list of integers
341
    The axes along which the FFT is carried out.
Martin Reinecke's avatar
Martin Reinecke committed
342
343
344
345
    If not set, all axes will be transformed in ascending order.
lastsize : the output size of the last axis to be transformed.
    If the corresponding input axis has size n, this can be 2*n-2 or 2*n-1.
fct : float
Martin Reinecke's avatar
Martin Reinecke committed
346
    Normalization factor
Martin Reinecke's avatar
Martin Reinecke committed
347
348
349
350

Returns
-------
np.ndarray (np.float32 or np.float64)
Martin Reinecke's avatar
Martin Reinecke committed
351
352
    The transformed data. The shape is identical to that of the input array,
    except for the axis that was transformed last, which has now `lastsize`
Martin Reinecke's avatar
Martin Reinecke committed
353
354
355
    entries.
)DELIM";

356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
const char *irfft_scipy_DS = R"DELIM(Performs a backward real-valued FFT.

Parameters
----------
a : numpy.ndarray (np.float32 or np.float64)
    The input data. Along the transformed axis, values are expected in
    FFTPACK half-complex order, i.e. `a[0].re, a[1].re, a[1].im, a[2].re ...`.
axis : int
    The axis along which the FFT is carried out.
fct : float
    Normalization factor
inplace : bool
    if False, returns the result in a new array and leaves the input unchanged.
    if True, stores the result in the input array and returns a handle to it.

Returns
-------
np.ndarray (np.float32 or np.float64)
    The transformed data. The shape is identical to that of the input array.
)DELIM";

377
const char *hartley_DS = R"DELIM(Performs a Hartley transform.
378
379
380
381
382
383
384
385
386
For every requested axis, a 1D forward Fourier transform is carried out,
and the sum of real and imaginary parts of the result is stored in the output
array.

Parameters
----------
a : numpy.ndarray (np.float32 or np.float64)
    The input data
axes : list of integers
387
    The axes along which the transform is carried out.
388
    If not set, all axes will be transformed.
Martin Reinecke's avatar
Martin Reinecke committed
389
fct : float
Martin Reinecke's avatar
Martin Reinecke committed
390
    Normalization factor
391
inplace : bool
Martin Reinecke's avatar
Martin Reinecke committed
392
    if False, returns the result in a new array and leaves the input unchanged.
393
    if True, stores the result in the input array and returns a handle to it.
394
395
396
397

Returns
-------
np.ndarray (same shape and data type as a)
Martin Reinecke's avatar
Martin Reinecke committed
398
    The transformed data
399
400
)DELIM";

Martin Reinecke's avatar
Martin Reinecke committed
401
402
} // unnamed namespace

403
404
#pragma GCC visibility pop

Martin Reinecke's avatar
Martin Reinecke committed
405
406
PYBIND11_MODULE(pypocketfft, m)
  {
Martin Reinecke's avatar
more  
Martin Reinecke committed
407
408
  using namespace pybind11::literals;

Martin Reinecke's avatar
Martin Reinecke committed
409
  m.doc() = pypocketfft_DS;
410
411
412
413
  m.def("fftn",&fftn, fftn_DS, "a"_a, "axes"_a=py::none(), "fct"_a=1.,
    "inplace"_a=false);
  m.def("ifftn",&ifftn, ifftn_DS, "a"_a, "axes"_a=py::none(), "fct"_a=1.,
    "inplace"_a=false);
Martin Reinecke's avatar
Martin Reinecke committed
414
  m.def("rfftn",&rfftn, rfftn_DS, "a"_a, "axes"_a=py::none(), "fct"_a=1.);
415
  m.def("rfft_scipy",&rfft_scipy, rfft_scipy_DS, "a"_a, "axis"_a, "fct"_a=1.,
416
    "inplace"_a=false);
417
418
  m.def("irfftn",&irfftn, irfftn_DS, "a"_a, "axes"_a=py::none(), "lastsize"_a=0,
    "fct"_a=1.);
419
420
  m.def("irfft_scipy",&irfft_scipy, irfft_scipy_DS, "a"_a, "axis"_a, "fct"_a=1.,
    "inplace"_a=false);
421
422
  m.def("hartley",&hartley, hartley_DS, "a"_a, "axes"_a=py::none(), "fct"_a=1.,
    "inplace"_a=false);
Martin Reinecke's avatar
Martin Reinecke committed
423
424
425
426
  m.def("hartley2",&hartley2, "a"_a, "axes"_a=py::none(), "fct"_a=1.,
    "inplace"_a=false);
  m.def("complex2hartley",&mycomplex2hartley, "in"_a, "tmp"_a, "axes"_a,
    "inplace"_a=false);
Martin Reinecke's avatar
Martin Reinecke committed
427
  }