pypocketfft.cc 12.7 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
Martin Reinecke committed
85
86
  c2c(dims, copy_strides(in), copy_strides(res), axes, fwd, in.data(),
    res.mutable_data(), T(fct));
Martin Reinecke's avatar
Martin Reinecke committed
87
88
  return res;
  }
Martin Reinecke's avatar
Martin Reinecke committed
89

90
91
py::array xfftn(const py::array &a, py::object axes, double fct, bool inplace,
  bool fwd)
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
92
  {
Martin Reinecke's avatar
cleanup  
Martin Reinecke committed
93
  return tcheck(a, c128, c64) ?
94
95
    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
96
  }
97
98
99
100
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
101

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

template<typename T> py::array hartley_internal(const py::array &in,
164
  py::object axes_, double fct, bool inplace)
Martin Reinecke's avatar
more  
Martin Reinecke committed
165
  {
Martin Reinecke's avatar
Martin Reinecke committed
166
  auto dims(copy_shape(in));
167
  py::array res = inplace ? in : py::array_t<T>(dims);
Martin Reinecke's avatar
Martin Reinecke committed
168
169
  r2r_hartley(dims, copy_strides(in), copy_strides(res), makeaxes(in, axes_),
    in.data(), res.mutable_data(), T(fct));
Martin Reinecke's avatar
Martin Reinecke committed
170
171
  return res;
  }
172
173
py::array hartley(const py::array &in, py::object axes_, double fct,
  bool inplace)
Martin Reinecke's avatar
Martin Reinecke committed
174
  {
175
176
177
  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
178
  }
179

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

Martin Reinecke's avatar
Martin Reinecke committed
232
const char *pypocketfft_DS = R"DELIM(Fast Fourier and Hartley transforms.
Martin Reinecke's avatar
Martin Reinecke committed
233
234
235
236
237
238
239
240
241
242
243

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";

244
245
246
247
248
249
250
251
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
252
    The axes along which the FFT is carried out.
253
    If not set, all axes will be transformed.
Martin Reinecke's avatar
Martin Reinecke committed
254
fct : float
Martin Reinecke's avatar
Martin Reinecke committed
255
    Normalization factor
256
inplace : bool
Martin Reinecke's avatar
Martin Reinecke committed
257
    if False, returns the result in a new array and leaves the input unchanged.
258
    if True, stores the result in the input array and returns a handle to it.
259
260
261
262

Returns
-------
np.ndarray (same shape and data type as a)
263
    The transformed data.
264
265
)DELIM";

Martin Reinecke's avatar
Martin Reinecke committed
266
const char *ifftn_DS = R"DELIM(Performs a backward complex FFT.
267
268
269
270
271
272

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

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

Martin Reinecke's avatar
Martin Reinecke committed
287
const char *rfftn_DS = R"DELIM(Performs a forward real-valued FFT.
Martin Reinecke's avatar
Martin Reinecke committed
288
289
290
291
292
293

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

Returns
-------
np.ndarray (np.complex64 or np.complex128)
Martin Reinecke's avatar
Martin Reinecke committed
302
    The transformed data. The shape is identical to that of the input array,
Martin Reinecke's avatar
Martin Reinecke committed
303
304
305
306
    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";

307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
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
329
const char *irfftn_DS = R"DELIM(Performs a backward real-valued FFT.
Martin Reinecke's avatar
Martin Reinecke committed
330
331
332
333
334
335

Parameters
----------
a : numpy.ndarray (np.complex64 or np.complex128)
    The input data
axes : list of integers
336
    The axes along which the FFT is carried out.
Martin Reinecke's avatar
Martin Reinecke committed
337
338
339
340
    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
341
    Normalization factor
Martin Reinecke's avatar
Martin Reinecke committed
342
343
344
345

Returns
-------
np.ndarray (np.float32 or np.float64)
Martin Reinecke's avatar
Martin Reinecke committed
346
347
    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
348
349
350
    entries.
)DELIM";

351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
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";

372
const char *hartley_DS = R"DELIM(Performs a Hartley transform.
373
374
375
376
377
378
379
380
381
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
382
    The axes along which the transform is carried out.
383
    If not set, all axes will be transformed.
Martin Reinecke's avatar
Martin Reinecke committed
384
fct : float
Martin Reinecke's avatar
Martin Reinecke committed
385
    Normalization factor
386
inplace : bool
Martin Reinecke's avatar
Martin Reinecke committed
387
    if False, returns the result in a new array and leaves the input unchanged.
388
    if True, stores the result in the input array and returns a handle to it.
389
390
391
392

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

Martin Reinecke's avatar
Martin Reinecke committed
396
397
} // unnamed namespace

398
399
#pragma GCC visibility pop

Martin Reinecke's avatar
Martin Reinecke committed
400
401
PYBIND11_MODULE(pypocketfft, m)
  {
Martin Reinecke's avatar
more  
Martin Reinecke committed
402
403
  using namespace pybind11::literals;

Martin Reinecke's avatar
Martin Reinecke committed
404
  m.doc() = pypocketfft_DS;
405
406
407
408
  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
409
  m.def("rfftn",&rfftn, rfftn_DS, "a"_a, "axes"_a=py::none(), "fct"_a=1.);
410
  m.def("rfft_scipy",&rfft_scipy, rfft_scipy_DS, "a"_a, "axis"_a, "fct"_a=1.,
411
    "inplace"_a=false);
412
413
  m.def("irfftn",&irfftn, irfftn_DS, "a"_a, "axes"_a=py::none(), "lastsize"_a=0,
    "fct"_a=1.);
414
415
  m.def("irfft_scipy",&irfft_scipy, irfft_scipy_DS, "a"_a, "axis"_a, "fct"_a=1.,
    "inplace"_a=false);
416
417
  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
418
419
420
421
  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
422
  }