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");
34
//auto c256 = py::dtype("complex256");
Martin Reinecke's avatar
Martin Reinecke committed
35
36
auto f32 = py::dtype("float32");
auto f64 = py::dtype("float64");
37
//auto f128 = py::dtype("float128");
Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
38
39

shape_t copy_shape(const py::array &arr)
Martin Reinecke's avatar
Martin Reinecke committed
40
  {
Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
41
  shape_t res(arr.ndim());
Martin Reinecke's avatar
Martin Reinecke committed
42
43
44
45
  for (size_t i=0; i<res.size(); ++i)
    res[i] = arr.shape(i);
  return res;
  }
Martin Reinecke's avatar
Martin Reinecke committed
46

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

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

73
74
75
76
77
78
79
#define DISPATCH(arr, T1, T2, T3, func, args) \
  auto dtype = arr.dtype(); \
  if (dtype.is(T1)) return func<double> args; \
  if (dtype.is(T2)) return func<float> args; \
/*  if (dtype.is(T3)) return func<long double> args; */ \
  throw runtime_error("unsupported data type");

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
  {
94
95
  DISPATCH(a, c128, c64, c256, xfftn_internal, (a, makeaxes(a, axes), fct,
           inplace, fwd))
Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
96
  }
97

98
99
py::array fftn(const py::array &a, py::object axes, double fct, bool inplace)
  { return xfftn(a, axes, fct, inplace, true); }
100

101
102
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
103

Martin Reinecke's avatar
Martin Reinecke committed
104
105
template<typename T> py::array rfftn_internal(const py::array &in,
  py::object axes_, T fct)
Martin Reinecke's avatar
Martin Reinecke committed
106
  {
Martin Reinecke's avatar
Martin Reinecke committed
107
  auto axes = makeaxes(in, axes_);
Martin Reinecke's avatar
Martin Reinecke committed
108
  auto dims_in(copy_shape(in)), dims_out(dims_in);
Martin Reinecke's avatar
more    
Martin Reinecke committed
109
  dims_out[axes.back()] = (dims_out[axes.back()]>>1)+1;
Martin Reinecke's avatar
Martin Reinecke committed
110
  py::array res = py::array_t<complex<T>>(dims_out);
Martin Reinecke's avatar
sync    
Martin Reinecke committed
111
112
113
  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
114
115
  return res;
  }
116

Martin Reinecke's avatar
Martin Reinecke committed
117
118
py::array rfftn(const py::array &in, py::object axes_, double fct)
  {
119
  DISPATCH(in, f64, f32, f128, rfftn_internal, (in, axes_, fct))
Martin Reinecke's avatar
Martin Reinecke committed
120
  }
121

122
template<typename T> py::array xrfft_scipy(const py::array &in,
Martin Reinecke's avatar
Martin Reinecke committed
123
  size_t axis, double fct, bool inplace, bool fwd)
124
125
126
  {
  auto dims(copy_shape(in));
  py::array res = inplace ? in : py::array_t<T>(dims);
Martin Reinecke's avatar
Martin Reinecke committed
127
  r2r_fftpack(dims, copy_strides(in), copy_strides(res), axis, fwd,
Martin Reinecke's avatar
sync    
Martin Reinecke committed
128
129
    reinterpret_cast<const T *>(in.data()),
    reinterpret_cast<T *>(res.mutable_data()), T(fct));
130
131
  return res;
  }
132

Martin Reinecke's avatar
Martin Reinecke committed
133
py::array rfft_scipy(const py::array &in, size_t axis, double fct, bool inplace)
134
  {
135
  DISPATCH(in, f64, f32, f128, xrfft_scipy, (in, axis, fct, inplace, true))
136
  }
137

Martin Reinecke's avatar
Martin Reinecke committed
138
139
py::array irfft_scipy(const py::array &in, size_t axis, double fct,
  bool inplace)
140
  {
141
  DISPATCH(in, f64, f32, f128, xrfft_scipy, (in, axis, fct, inplace, false))
142
  }
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;
  }
159

Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
160
161
162
py::array irfftn(const py::array &in, py::object axes_, size_t lastsize,
  double fct)
  {
163
  DISPATCH(in, c128, c64, c256, irfftn_internal, (in, axes_, lastsize, fct))
Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
164
  }
Martin Reinecke's avatar
Martin Reinecke committed
165
166

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

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
  DISPATCH(in, f64, f32, f128, hartley_internal, (in, axes_, fct, inplace))
Martin Reinecke's avatar
Martin Reinecke committed
181
  }
182

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

226
py::array mycomplex2hartley(const py::array &in,
Martin Reinecke's avatar
Martin Reinecke committed
227
  const py::array &tmp, py::object axes_, bool inplace)
228
  {
229
  DISPATCH(in, f64, f32, f128, complex2hartley, (in, tmp, axes_, inplace))
230
  }
231

Martin Reinecke's avatar
Martin Reinecke committed
232
233
234
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
235

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

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

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

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

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

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

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

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

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

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

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

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

Returns
-------
np.ndarray (np.float32 or np.float64)
Martin Reinecke's avatar
Martin Reinecke committed
350
351
    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
352
353
354
    entries.
)DELIM";

355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
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";

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

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

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

402
403
#pragma GCC visibility pop

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

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