1# cython: language_level=3
2#
3# Copyright 2015 Knowledge Economy Developments Ltd
4# Copyright 2014 David Wells
5
6# Henry Gomersall
7# heng@kedevelopments.co.uk
8#
9# All rights reserved.
10#
11# Redistribution and use in source and binary forms, with or without
12# modification, are permitted provided that the following conditions are met:
13#
14# * Redistributions of source code must retain the above copyright notice, this
15# list of conditions and the following disclaimer.
16#
17# * Redistributions in binary form must reproduce the above copyright notice,
18# this list of conditions and the following disclaimer in the documentation
19# and/or other materials provided with the distribution.
20#
21# * Neither the name of the copyright holder nor the names of its contributors
22# may be used to endorse or promote products derived from this software without
23# specific prior written permission.
24#
25# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35# POSSIBILITY OF SUCH DAMAGE.
36#
37
38import numpy as np
39cimport numpy as np
40from libc.stdlib cimport calloc, malloc, free
41from libc.stdint cimport intptr_t, int64_t
42from libc cimport limits
43
44import warnings
45import threading
46
47include 'utils.pxi'
48
49cdef extern from *:
50    int Py_AtExit(void (*callback)())
51
52# the total number of types pyfftw can support
53cdef int _n_types = 3
54cdef object _all_types = ['32', '64', 'ld']
55_all_types_human_readable = {
56    '32': 'single',
57    '64': 'double',
58    'ld': 'long double',
59}
60
61_all_types_np = {
62    np.dtype(np.float32): '32',
63    np.dtype(np.float64): '64',
64}
65if np.dtype(np.longdouble) != np.dtype(np.float64):
66    _all_types_np[np.dtype(np.longdouble)] = 'ld'
67
68# the types supported in this build
69_supported_types = []
70_supported_nptypes_complex = []
71_supported_nptypes_real = []
72
73IF HAVE_SINGLE:
74    _supported_types.append('32')
75    _supported_nptypes_complex.append(np.complex64)
76    _supported_nptypes_real.append(np.float32)
77IF HAVE_DOUBLE:
78    _supported_types.append('64')
79    _supported_nptypes_complex.append(np.complex128)
80    _supported_nptypes_real.append(np.float64)
81IF HAVE_LONG:
82    _supported_types.append('ld')
83    _supported_nptypes_complex.append(np.clongdouble)
84    _supported_nptypes_real.append(np.longdouble)
85
86IF (HAVE_SINGLE_OMP or HAVE_DOUBLE_OMP or HAVE_LONG_OMP):
87    _threading_type = 'OMP'
88ELIF (HAVE_SINGLE_THREADS or HAVE_DOUBLE_THREADS or HAVE_LONG_THREADS):
89    _threading_type = 'PTHREADS'
90ELSE:
91    _threading_type = None
92
93cdef object directions
94directions = {'FFTW_FORWARD': FFTW_FORWARD,
95        'FFTW_BACKWARD': FFTW_BACKWARD,
96        'FFTW_REDFT00': FFTW_REDFT00,
97        'FFTW_REDFT10': FFTW_REDFT10,
98        'FFTW_REDFT01': FFTW_REDFT01,
99        'FFTW_REDFT11': FFTW_REDFT11,
100        'FFTW_RODFT00': FFTW_RODFT00,
101        'FFTW_RODFT10': FFTW_RODFT10,
102        'FFTW_RODFT01': FFTW_RODFT01,
103        'FFTW_RODFT11': FFTW_RODFT11}
104
105cdef object directions_lookup
106directions_lookup = {FFTW_FORWARD: 'FFTW_FORWARD',
107        FFTW_BACKWARD: 'FFTW_BACKWARD',
108        FFTW_REDFT00: 'FFTW_REDFT00',
109        FFTW_REDFT10: 'FFTW_REDFT10',
110        FFTW_REDFT01: 'FFTW_REDFT01',
111        FFTW_REDFT11: 'FFTW_REDFT11',
112        FFTW_RODFT00: 'FFTW_RODFT00',
113        FFTW_RODFT10: 'FFTW_RODFT10',
114        FFTW_RODFT01: 'FFTW_RODFT01',
115        FFTW_RODFT11: 'FFTW_RODFT11'}
116
117cdef object flag_dict
118flag_dict = {'FFTW_MEASURE': FFTW_MEASURE,
119        'FFTW_EXHAUSTIVE': FFTW_EXHAUSTIVE,
120        'FFTW_PATIENT': FFTW_PATIENT,
121        'FFTW_ESTIMATE': FFTW_ESTIMATE,
122        'FFTW_UNALIGNED': FFTW_UNALIGNED,
123        'FFTW_DESTROY_INPUT': FFTW_DESTROY_INPUT,
124        'FFTW_WISDOM_ONLY': FFTW_WISDOM_ONLY}
125
126_flag_dict = flag_dict.copy()
127
128# Need a global lock to protect FFTW planning so that multiple Python threads
129# do not attempt to plan simultaneously.
130cdef object plan_lock = threading.Lock()
131
132# Function wrappers
133# =================
134# All of these have the same signature as the fftw_generic functions
135# defined in the .pxd file. The arguments and return values are
136# cast as required in order to call the actual fftw functions.
137#
138# The wrapper function names are simply the fftw names prefixed
139# with a single underscore.
140
141#     Planners
142#     ========
143#
144
145cdef void* _fftw_plan_null(
146            int rank, fftw_iodim *dims,
147            int howmany_rank, fftw_iodim *howmany_dims,
148            void *_in, void *_out,
149            int *direction, unsigned flags):
150
151    raise RuntimeError("Undefined planner. This is a bug")
152
153# Complex double precision
154IF HAVE_DOUBLE:
155    cdef void* _fftw_plan_guru_dft(
156                int rank, fftw_iodim *dims,
157                int howmany_rank, fftw_iodim *howmany_dims,
158                void *_in, void *_out,
159                int *direction, unsigned flags) nogil:
160
161        return <void *>fftw_plan_guru_dft(rank, dims,
162                howmany_rank, howmany_dims,
163                <cdouble *>_in, <cdouble *>_out,
164                direction[0], flags)
165
166    # real to complex double precision
167    cdef void* _fftw_plan_guru_dft_r2c(
168                int rank, fftw_iodim *dims,
169                int howmany_rank, fftw_iodim *howmany_dims,
170                void *_in, void *_out,
171                int *direction, unsigned flags) nogil:
172
173        return <void *>fftw_plan_guru_dft_r2c(rank, dims,
174                howmany_rank, howmany_dims,
175                <double *>_in, <cdouble *>_out,
176                flags)
177
178    # complex to real double precision
179    cdef void* _fftw_plan_guru_dft_c2r(
180                int rank, fftw_iodim *dims,
181                int howmany_rank, fftw_iodim *howmany_dims,
182                void *_in, void *_out,
183                int *direction, unsigned flags) nogil:
184
185        return <void *>fftw_plan_guru_dft_c2r(rank, dims,
186                howmany_rank, howmany_dims,
187                <cdouble *>_in, <double *>_out,
188                flags)
189
190    # real to real double precision
191    cdef void* _fftw_plan_guru_r2r(
192                int rank, fftw_iodim *dims,
193                int howmany_rank, fftw_iodim *howmany_dims,
194                void *_in, void *_out,
195                int *direction, int flags):
196
197        return <void *>fftw_plan_guru_r2r(rank, dims,
198                howmany_rank, howmany_dims,
199                <double *>_in, <double *>_out,
200                direction, flags)
201
202IF HAVE_SINGLE:
203    # Complex single precision
204    cdef void* _fftwf_plan_guru_dft(
205                int rank, fftw_iodim *dims,
206                int howmany_rank, fftw_iodim *howmany_dims,
207                void *_in, void *_out,
208                int *direction, unsigned flags) nogil:
209
210        return <void *>fftwf_plan_guru_dft(rank, dims,
211                howmany_rank, howmany_dims,
212                <cfloat *>_in, <cfloat *>_out,
213                direction[0], flags)
214
215    # real to complex single precision
216    cdef void* _fftwf_plan_guru_dft_r2c(
217                int rank, fftw_iodim *dims,
218                int howmany_rank, fftw_iodim *howmany_dims,
219                void *_in, void *_out,
220                int *direction, unsigned flags) nogil:
221
222        return <void *>fftwf_plan_guru_dft_r2c(rank, dims,
223                howmany_rank, howmany_dims,
224                <float *>_in, <cfloat *>_out,
225                flags)
226
227    # complex to real single precision
228    cdef void* _fftwf_plan_guru_dft_c2r(
229                int rank, fftw_iodim *dims,
230                int howmany_rank, fftw_iodim *howmany_dims,
231                void *_in, void *_out,
232                int *direction, unsigned flags) nogil:
233
234        return <void *>fftwf_plan_guru_dft_c2r(rank, dims,
235                howmany_rank, howmany_dims,
236                <cfloat *>_in, <float *>_out,
237                flags)
238
239    # real to real single precision
240    cdef void* _fftwf_plan_guru_r2r(
241                int rank, fftw_iodim *dims,
242                int howmany_rank, fftw_iodim *howmany_dims,
243                void *_in, void *_out,
244                int *direction, int flags):
245
246        return <void *>fftwf_plan_guru_r2r(rank, dims,
247                howmany_rank, howmany_dims,
248                <float *>_in, <float *>_out,
249                direction, flags)
250
251IF HAVE_LONG:
252    # Complex long double precision
253    cdef void* _fftwl_plan_guru_dft(
254                int rank, fftw_iodim *dims,
255                int howmany_rank, fftw_iodim *howmany_dims,
256                void *_in, void *_out,
257                int *direction, unsigned flags) nogil:
258
259        return <void *>fftwl_plan_guru_dft(rank, dims,
260                howmany_rank, howmany_dims,
261                <clongdouble *>_in, <clongdouble *>_out,
262                direction[0], flags)
263
264    # real to complex long double precision
265    cdef void* _fftwl_plan_guru_dft_r2c(
266                int rank, fftw_iodim *dims,
267                int howmany_rank, fftw_iodim *howmany_dims,
268                void *_in, void *_out,
269                int *direction, unsigned flags) nogil:
270
271        return <void *>fftwl_plan_guru_dft_r2c(rank, dims,
272                howmany_rank, howmany_dims,
273                <long double *>_in, <clongdouble *>_out,
274                flags)
275
276    # complex to real long double precision
277    cdef void* _fftwl_plan_guru_dft_c2r(
278                int rank, fftw_iodim *dims,
279                int howmany_rank, fftw_iodim *howmany_dims,
280                void *_in, void *_out,
281                int *direction, unsigned flags) nogil:
282
283        return <void *>fftwl_plan_guru_dft_c2r(rank, dims,
284                howmany_rank, howmany_dims,
285                <clongdouble *>_in, <long double *>_out,
286                flags)
287
288    # real to real long double precision
289    cdef void* _fftwl_plan_guru_r2r(
290                int rank, fftw_iodim *dims,
291                int howmany_rank, fftw_iodim *howmany_dims,
292                void *_in, void *_out,
293                int *direction, int flags):
294
295        return <void *>fftwl_plan_guru_r2r(rank, dims,
296                howmany_rank, howmany_dims,
297                <long double *>_in, <long double *>_out,
298                direction, flags)
299
300#    Executors
301#    =========
302#
303
304cdef void _fftw_execute_null(void *_plan, void *_in, void *_out):
305
306    raise RuntimeError("Undefined executor. This is a bug")
307
308IF HAVE_DOUBLE:
309    # Complex double precision
310    cdef void _fftw_execute_dft(void *_plan, void *_in, void *_out) nogil:
311
312        fftw_execute_dft(<fftw_plan>_plan,
313                <cdouble *>_in, <cdouble *>_out)
314
315    # real to complex double precision
316    cdef void _fftw_execute_dft_r2c(void *_plan, void *_in, void *_out) nogil:
317
318        fftw_execute_dft_r2c(<fftw_plan>_plan,
319                <double *>_in, <cdouble *>_out)
320
321    # complex to real double precision
322    cdef void _fftw_execute_dft_c2r(void *_plan, void *_in, void *_out) nogil:
323
324        fftw_execute_dft_c2r(<fftw_plan>_plan,
325                <cdouble *>_in, <double *>_out)
326
327IF HAVE_SINGLE:
328    # Complex single precision
329    cdef void _fftwf_execute_dft(void *_plan, void *_in, void *_out) nogil:
330
331        fftwf_execute_dft(<fftwf_plan>_plan,
332                <cfloat *>_in, <cfloat *>_out)
333
334    # real to complex single precision
335    cdef void _fftwf_execute_dft_r2c(void *_plan, void *_in, void *_out) nogil:
336
337        fftwf_execute_dft_r2c(<fftwf_plan>_plan,
338                <float *>_in, <cfloat *>_out)
339
340    # complex to real single precision
341    cdef void _fftwf_execute_dft_c2r(void *_plan, void *_in, void *_out) nogil:
342
343        fftwf_execute_dft_c2r(<fftwf_plan>_plan,
344                <cfloat *>_in, <float *>_out)
345
346IF HAVE_LONG:
347    # Complex long double precision
348    cdef void _fftwl_execute_dft(void *_plan, void *_in, void *_out) nogil:
349
350        fftwl_execute_dft(<fftwl_plan>_plan,
351                <clongdouble *>_in, <clongdouble *>_out)
352
353    # real to complex long double precision
354    cdef void _fftwl_execute_dft_r2c(void *_plan, void *_in, void *_out) nogil:
355
356        fftwl_execute_dft_r2c(<fftwl_plan>_plan,
357                <long double *>_in, <clongdouble *>_out)
358
359    # complex to real long double precision
360    cdef void _fftwl_execute_dft_c2r(void *_plan, void *_in, void *_out) nogil:
361
362        fftwl_execute_dft_c2r(<fftwl_plan>_plan,
363                <clongdouble *>_in, <long double *>_out)
364
365# real to real double precision
366cdef void _fftw_execute_r2r(void *_plan, void *_in, void *_out) nogil:
367
368    fftw_execute_r2r(<fftw_plan>_plan, <double *>_in, <double *>_out)
369
370# real to real single precision
371cdef void _fftwf_execute_r2r(void *_plan, void *_in, void *_out) nogil:
372
373    fftwf_execute_r2r(<fftwf_plan>_plan, <float *>_in, <float *>_out)
374
375# real to real long double precision
376cdef void _fftwl_execute_r2r(void *_plan, void *_in, void *_out) nogil:
377
378    fftwl_execute_r2r(<fftwl_plan>_plan, <long double *>_in, <long double *>_out)
379
380#    Destroyers
381#    ==========
382#
383cdef void _fftw_destroy_null(void *plan):
384
385    raise RuntimeError("Undefined destroy. This is a bug")
386
387IF HAVE_DOUBLE:
388    # Double precision
389    cdef void _fftw_destroy_plan(void *_plan):
390
391        fftw_destroy_plan(<fftw_plan>_plan)
392
393IF HAVE_SINGLE:
394    # Single precision
395    cdef void _fftwf_destroy_plan(void *_plan):
396
397        fftwf_destroy_plan(<fftwf_plan>_plan)
398
399IF HAVE_LONG:
400    # Long double precision
401    cdef void _fftwl_destroy_plan(void *_plan):
402
403        fftwl_destroy_plan(<fftwl_plan>_plan)
404
405# Function lookup tables
406# ======================
407
408
409# Planner table (of size the number of planners).
410cdef fftw_generic_plan_guru planners[12]
411
412cdef fftw_generic_plan_guru * _build_planner_list():
413    for i in range(12):
414        planners[i] = <fftw_generic_plan_guru>&_fftw_plan_null
415
416    IF HAVE_DOUBLE:
417        planners[0] = <fftw_generic_plan_guru>&_fftw_plan_guru_dft
418        planners[3] = <fftw_generic_plan_guru>&_fftw_plan_guru_dft_r2c
419        planners[6] = <fftw_generic_plan_guru>&_fftw_plan_guru_dft_c2r
420        planners[9] = <fftw_generic_plan_guru>&_fftw_plan_guru_r2r
421    IF HAVE_SINGLE:
422        planners[1] = <fftw_generic_plan_guru>&_fftwf_plan_guru_dft
423        planners[4] = <fftw_generic_plan_guru>&_fftwf_plan_guru_dft_r2c
424        planners[7] = <fftw_generic_plan_guru>&_fftwf_plan_guru_dft_c2r
425        planners[10] = <fftw_generic_plan_guru>&_fftwf_plan_guru_r2r
426    IF HAVE_LONG:
427        planners[2] = <fftw_generic_plan_guru>&_fftwl_plan_guru_dft
428        planners[5] = <fftw_generic_plan_guru>&_fftwl_plan_guru_dft_r2c
429        planners[8] = <fftw_generic_plan_guru>&_fftwl_plan_guru_dft_c2r
430        planners[11] = <fftw_generic_plan_guru>&_fftwl_plan_guru_r2r
431
432# Executor table (of size the number of executors)
433cdef fftw_generic_execute executors[12]
434
435cdef fftw_generic_execute * _build_executor_list():
436    for i in range(12):
437        executors[i] = <fftw_generic_execute>&_fftw_execute_null
438
439    IF HAVE_DOUBLE:
440        executors[0] = <fftw_generic_execute>&_fftw_execute_dft
441        executors[3] = <fftw_generic_execute>&_fftw_execute_dft_r2c
442        executors[6] = <fftw_generic_execute>&_fftw_execute_dft_c2r
443        executors[9] = <fftw_generic_execute>&_fftw_execute_r2r
444    IF HAVE_SINGLE:
445        executors[1] = <fftw_generic_execute>&_fftwf_execute_dft
446        executors[4] = <fftw_generic_execute>&_fftwf_execute_dft_r2c
447        executors[7] = <fftw_generic_execute>&_fftwf_execute_dft_c2r
448        executors[10] = <fftw_generic_execute>&_fftwf_execute_r2r
449    IF HAVE_LONG:
450        executors[2] = <fftw_generic_execute>&_fftwl_execute_dft
451        executors[5] = <fftw_generic_execute>&_fftwl_execute_dft_r2c
452        executors[8] = <fftw_generic_execute>&_fftwl_execute_dft_c2r
453        executors[11] = <fftw_generic_execute>&_fftwl_execute_r2r
454
455# Destroyer table (of size the number of destroyers)
456cdef fftw_generic_destroy_plan destroyers[3]
457
458cdef fftw_generic_destroy_plan * _build_destroyer_list():
459    for i in range(3):
460        destroyers[i] = <fftw_generic_destroy_plan>&_fftw_destroy_null
461
462    IF HAVE_DOUBLE:
463        destroyers[0] = <fftw_generic_destroy_plan>&_fftw_destroy_plan
464    IF HAVE_SINGLE:
465        destroyers[1] = <fftw_generic_destroy_plan>&_fftwf_destroy_plan
466    IF HAVE_LONG:
467        destroyers[2] = <fftw_generic_destroy_plan>&_fftwl_destroy_plan
468
469# nthreads plan setters table
470cdef fftw_generic_plan_with_nthreads nthreads_plan_setters[3]
471
472cdef void _fftw_plan_with_nthreads_null(int n):
473
474    raise RuntimeError("Undefined plan with nthreads. This is a bug")
475
476cdef fftw_generic_plan_with_nthreads * _build_nthreads_plan_setters_list():
477    for i in range(3):
478        nthreads_plan_setters[i] = (
479            <fftw_generic_plan_with_nthreads>&_fftw_plan_with_nthreads_null)
480    IF HAVE_DOUBLE_MULTITHREADING:
481        nthreads_plan_setters[0] = (
482            <fftw_generic_plan_with_nthreads>&fftw_plan_with_nthreads)
483    IF HAVE_SINGLE_MULTITHREADING:
484        nthreads_plan_setters[1] = (
485            <fftw_generic_plan_with_nthreads>&fftwf_plan_with_nthreads)
486    IF HAVE_LONG_MULTITHREADING:
487        nthreads_plan_setters[2] = (
488            <fftw_generic_plan_with_nthreads>&fftwl_plan_with_nthreads)
489
490# Set planner timelimits
491cdef fftw_generic_set_timelimit set_timelimit_funcs[3]
492
493cdef void _fftw_generic_set_timelimit_null(void *plan):
494
495    raise RuntimeError("Undefined set timelimit. This is a bug")
496
497cdef fftw_generic_set_timelimit * _build_set_timelimit_funcs_list():
498    for i in range(3):
499        set_timelimit_funcs[i] = (
500            <fftw_generic_set_timelimit>&_fftw_generic_set_timelimit_null)
501
502    IF HAVE_DOUBLE:
503        set_timelimit_funcs[0] = (
504            <fftw_generic_set_timelimit>&fftw_set_timelimit)
505    IF HAVE_SINGLE:
506        set_timelimit_funcs[1] = (
507            <fftw_generic_set_timelimit>&fftwf_set_timelimit)
508    IF HAVE_LONG:
509        set_timelimit_funcs[2] = (
510            <fftw_generic_set_timelimit>&fftwl_set_timelimit)
511
512# Data validators table
513cdef validator validators[2]
514
515cdef validator * _build_validators_list():
516    validators[0] = &_validate_r2c_arrays
517    validators[1] = &_validate_c2r_arrays
518
519# Validator functions
520# ===================
521cdef bint _validate_r2c_arrays(np.ndarray input_array,
522        np.ndarray output_array, int64_t *axes, int64_t *not_axes,
523        int64_t axes_length):
524    ''' Validates the input and output array to check for
525    a valid real to complex transform.
526    '''
527    # We firstly need to confirm that the dimenions of the arrays
528    # are the same
529    if not (input_array.ndim == output_array.ndim):
530        return False
531
532    in_shape = input_array.shape
533    out_shape = output_array.shape
534
535    for n in range(axes_length - 1):
536        if not out_shape[axes[n]] == in_shape[axes[n]]:
537            return False
538
539    # The critical axis is the last of those over which the
540    # FFT is taken.
541    if not (out_shape[axes[axes_length-1]]
542            == in_shape[axes[axes_length-1]]//2 + 1):
543        return False
544
545    for n in range(input_array.ndim - axes_length):
546        if not out_shape[not_axes[n]] == in_shape[not_axes[n]]:
547            return False
548
549    return True
550
551
552cdef bint _validate_c2r_arrays(np.ndarray input_array,
553        np.ndarray output_array, int64_t *axes, int64_t *not_axes,
554        int64_t axes_length):
555    ''' Validates the input and output array to check for
556    a valid complex to real transform.
557    '''
558
559    # We firstly need to confirm that the dimenions of the arrays
560    # are the same
561    if not (input_array.ndim == output_array.ndim):
562        return False
563
564    in_shape = input_array.shape
565    out_shape = output_array.shape
566
567    for n in range(axes_length - 1):
568        if not in_shape[axes[n]] == out_shape[axes[n]]:
569            return False
570
571    # The critical axis is the last of those over which the
572    # FFT is taken.
573    if not (in_shape[axes[axes_length-1]]
574            == out_shape[axes[axes_length-1]]//2 + 1):
575        return False
576
577    for n in range(input_array.ndim - axes_length):
578        if not in_shape[not_axes[n]] == out_shape[not_axes[n]]:
579            return False
580
581    return True
582
583
584# Shape lookup functions
585# ======================
586def _lookup_shape_r2c_arrays(input_array, output_array):
587    return input_array.shape
588
589def _lookup_shape_c2r_arrays(input_array, output_array):
590    return output_array.shape
591
592# fftw_schemes is a dictionary with a mapping from a keys,
593# which are a tuple of the string representation of numpy
594# dtypes to a scheme name.
595#
596# scheme_functions is a dictionary of functions, either
597# an index to the array of functions in the case of
598# 'planner', 'executor' and 'generic_precision' or a callable
599# in the case of 'validator' (generic_precision is a catchall for
600# functions that only change based on the precision changing -
601# i.e the prefix fftw, fftwl and fftwf is the only bit that changes).
602#
603# The array indices refer to the relevant functions for each scheme,
604# the tables to which are defined above.
605#
606# The 'validator' function is a callable for validating the arrays
607# that has the following signature:
608# bool callable(ndarray in_array, ndarray out_array, axes, not_axes)
609# and checks that the arrays are a valid pair. If it is set to None,
610# then the default check is applied, which confirms that the arrays
611# have the same shape.
612#
613# The 'fft_shape_lookup' function is a callable for returning the
614# FFT shape - that is, an array that describes the length of the
615# fft along each axis. It has the following signature:
616# fft_shape = fft_shape_lookup(in_array, out_array)
617# (note that this does not correspond to the lengths of the FFT that is
618# actually taken, it's the lengths of the FFT that *could* be taken
619# along each axis. It's necessary because the real FFT has a length
620# that is different to the length of the input array).
621
622cdef object fftw_schemes
623fftw_schemes = {
624        (np.dtype('complex128'), np.dtype('complex128')): ('c2c', '64'),
625        (np.dtype('complex64'), np.dtype('complex64')): ('c2c', '32'),
626        (np.dtype('float64'), np.dtype('complex128')): ('r2c', '64'),
627        (np.dtype('float32'), np.dtype('complex64')): ('r2c', '32'),
628        (np.dtype('complex128'), np.dtype('float64')): ('c2r', '64'),
629        (np.dtype('complex64'), np.dtype('float32')): ('c2r', '32'),
630        (np.dtype('float32'), np.dtype('float32')): ('r2r', '32'),
631        (np.dtype('float64'), np.dtype('float64')): ('r2r', '64')}
632
633cdef object fftw_default_output
634fftw_default_output = {
635    np.dtype('float32'): np.dtype('complex64'),
636    np.dtype('float64'): np.dtype('complex128'),
637    np.dtype('complex64'): np.dtype('complex64'),
638    np.dtype('complex128'): np.dtype('complex128')}
639
640if np.dtype('longdouble') != np.dtype('float64'):
641    fftw_schemes.update({
642        (np.dtype('clongdouble'), np.dtype('clongdouble')): ('c2c', 'ld'),
643        (np.dtype('longdouble'), np.dtype('clongdouble')): ('r2c', 'ld'),
644        (np.dtype('clongdouble'), np.dtype('longdouble')): ('c2r', 'ld'),
645        (np.dtype('longdouble'), np.dtype('longdouble')): ('r2r', 'ld')})
646
647    fftw_default_output.update({
648        np.dtype('longdouble'): np.dtype('clongdouble'),
649        np.dtype('clongdouble'): np.dtype('clongdouble')})
650
651cdef object scheme_directions
652scheme_directions = {
653        ('c2c', '64'): ['FFTW_FORWARD', 'FFTW_BACKWARD'],
654        ('c2c', '32'): ['FFTW_FORWARD', 'FFTW_BACKWARD'],
655        ('c2c', 'ld'): ['FFTW_FORWARD', 'FFTW_BACKWARD'],
656        ('r2c', '64'): ['FFTW_FORWARD'],
657        ('r2c', '32'): ['FFTW_FORWARD'],
658        ('r2c', 'ld'): ['FFTW_FORWARD'],
659        ('c2r', '64'): ['FFTW_BACKWARD'],
660        ('c2r', '32'): ['FFTW_BACKWARD'],
661        ('c2r', 'ld'): ['FFTW_BACKWARD'],
662        ('r2r', '64'): ['FFTW_REDFT00', 'FFTW_REDFT10', 'FFTW_REDFT01',
663                        'FFTW_REDFT11', 'FFTW_RODFT00', 'FFTW_RODFT10',
664                        'FFTW_RODFT01', 'FFTW_RODFT11'],
665        ('r2r', '32'): ['FFTW_REDFT00', 'FFTW_REDFT10', 'FFTW_REDFT01',
666                        'FFTW_REDFT11', 'FFTW_RODFT00', 'FFTW_RODFT10',
667                        'FFTW_RODFT01', 'FFTW_RODFT11'],
668        ('r2r', 'ld'): ['FFTW_REDFT00', 'FFTW_REDFT10', 'FFTW_REDFT01',
669                        'FFTW_REDFT11', 'FFTW_RODFT00', 'FFTW_RODFT10',
670                        'FFTW_RODFT01', 'FFTW_RODFT11']}
671
672# In the following, -1 denotes using the default. A segfault has been
673# reported on some systems when this is set to None. It seems
674# sufficiently trivial to use -1 in place of None, especially given
675# that scheme_functions is an internal cdef object.
676cdef object _scheme_functions = {}
677IF HAVE_DOUBLE:
678    _scheme_functions.update({
679    ('c2c', '64'): {'planner': 0, 'executor':0, 'generic_precision':0,
680        'validator': -1, 'fft_shape_lookup': -1},
681    ('r2c', '64'): {'planner':3, 'executor':3, 'generic_precision':0,
682        'validator': 0,
683        'fft_shape_lookup': _lookup_shape_r2c_arrays},
684    ('c2r', '64'): {'planner':6, 'executor':6, 'generic_precision':0,
685        'validator': 1,
686        'fft_shape_lookup': _lookup_shape_c2r_arrays},
687    ('r2r', '64'): {'planner': 9, 'executor':9, 'generic_precision':0,
688        'validator': -1, 'fft_shape_lookup': -1}})
689IF HAVE_SINGLE:
690    _scheme_functions.update({
691    ('c2c', '32'): {'planner':1, 'executor':1, 'generic_precision':1,
692        'validator': -1, 'fft_shape_lookup': -1},
693    ('r2c', '32'): {'planner':4, 'executor':4, 'generic_precision':1,
694        'validator': 0,
695        'fft_shape_lookup': _lookup_shape_r2c_arrays},
696    ('c2r', '32'): {'planner':7, 'executor':7, 'generic_precision':1,
697        'validator': 1,
698        'fft_shape_lookup': _lookup_shape_c2r_arrays},
699    ('r2r', '32'): {'planner':10, 'executor':10, 'generic_precision':1,
700        'validator': -1, 'fft_shape_lookup': -1}})
701IF HAVE_LONG:
702    _scheme_functions.update({
703    ('c2c', 'ld'): {'planner':2, 'executor':2, 'generic_precision':2,
704        'validator': -1, 'fft_shape_lookup': -1},
705    ('r2c', 'ld'): {'planner':5, 'executor':5, 'generic_precision':2,
706        'validator': 0,
707        'fft_shape_lookup': _lookup_shape_r2c_arrays},
708    ('c2r', 'ld'): {'planner':8, 'executor':8, 'generic_precision':2,
709        'validator': 1,
710        'fft_shape_lookup': _lookup_shape_c2r_arrays},
711    ('r2r', 'ld'): {'planner':11, 'executor':11, 'generic_precision':2,
712        'validator': -1, 'fft_shape_lookup': -1}})
713
714def scheme_functions(scheme):
715    if scheme in _scheme_functions:
716        return _scheme_functions[scheme]
717    else:
718        msg = "The scheme '%s' is not supported." % str(scheme)
719        if scheme[1] in _all_types:
720            msg += "\nRebuild pyFFTW with support for %s precision!" % \
721                   _all_types_human_readable[scheme[1]]
722        raise NotImplementedError(msg)
723
724# Set the cleanup routine
725cdef void _cleanup():
726    IF HAVE_DOUBLE:
727        fftw_cleanup()
728    IF HAVE_SINGLE:
729        fftwf_cleanup()
730    IF HAVE_LONG:
731        fftwl_cleanup()
732    IF HAVE_DOUBLE_MULTITHREADING:
733        fftw_cleanup_threads()
734    IF HAVE_SINGLE_MULTITHREADING:
735        fftwf_cleanup_threads()
736    IF HAVE_LONG_MULTITHREADING:
737        fftwl_cleanup_threads()
738
739# Initialize the module
740
741# Define the functions
742_build_planner_list()
743_build_destroyer_list()
744_build_executor_list()
745_build_nthreads_plan_setters_list()
746_build_validators_list()
747_build_set_timelimit_funcs_list()
748
749IF HAVE_DOUBLE_MULTITHREADING:
750    fftw_init_threads()
751IF HAVE_SINGLE_MULTITHREADING:
752    fftwf_init_threads()
753IF HAVE_LONG_MULTITHREADING:
754    fftwl_init_threads()
755
756Py_AtExit(_cleanup)
757
758# Helper functions
759cdef void make_axes_unique(int64_t *axes, int64_t axes_length,
760        int64_t **unique_axes, int64_t **not_axes, int64_t dimensions,
761        int64_t *unique_axes_length):
762    ''' Takes an array of axes and makes that array unique, returning
763    the unique array in unique_axes. It also creates and fills another
764    array, not_axes, with those axes that are not included in unique_axes.
765
766    unique_axes_length is updated with the length of unique_axes.
767
768    dimensions is the number of dimensions to which the axes array
769    might refer.
770
771    It is the responsibility of the caller to free unique_axes and not_axes.
772    '''
773
774    cdef int64_t unique_axes_count = 0
775    cdef int64_t holding_offset = 0
776
777    cdef int64_t *axes_holding = (
778            <int64_t *>calloc(dimensions, sizeof(int64_t)))
779    cdef int64_t *axes_holding_offset = (
780            <int64_t *>calloc(dimensions, sizeof(int64_t)))
781
782    for n in range(dimensions):
783        axes_holding[n] = -1
784
785    # Iterate over all the axes and store each index if it hasn't already
786    # been stored (this keeps one and only one and the first index to axes
787    # i.e. storing the unique set of entries).
788    #
789    # axes_holding_offset holds the shift due to repeated axes
790    for n in range(axes_length):
791        if axes_holding[axes[n]] == -1:
792            axes_holding[axes[n]] = n
793            axes_holding_offset[axes[n]] = holding_offset
794            unique_axes_count += 1
795        else:
796            holding_offset += 1
797
798    unique_axes[0] = <int64_t *>malloc(
799            unique_axes_count * sizeof(int64_t))
800
801    not_axes[0] = <int64_t *>malloc(
802            (dimensions - unique_axes_count) * sizeof(int64_t))
803
804    # Now we need to write back the unique axes to a tmp axes
805    cdef int64_t not_axes_count = 0
806
807    for n in range(dimensions):
808        if axes_holding[n] != -1:
809            unique_axes[0][axes_holding[n] - axes_holding_offset[n]] = (
810                    axes[axes_holding[n]])
811
812        else:
813            not_axes[0][not_axes_count] = n
814            not_axes_count += 1
815
816    free(axes_holding)
817    free(axes_holding_offset)
818
819    unique_axes_length[0] = unique_axes_count
820
821    return
822
823
824# The External Interface
825# ======================
826#
827cdef class FFTW:
828    '''
829    FFTW is a class for computing a variety of discrete Fourier
830    transforms of multidimensional, strided arrays using the FFTW
831    library. The interface is designed to be somewhat pythonic, with
832    the correct transform being inferred from the dtypes of the passed
833    arrays.
834
835    The exact scheme may be either directly specified with the
836    ``direction`` parameter or inferred from the dtypes and relative
837    shapes of the input arrays. Information on which shapes and dtypes
838    imply which transformations is available in the :ref:`FFTW schemes
839    <scheme_table>`. If a match is found, the plan corresponding to that
840    scheme is created, operating on the arrays that are passed in. If no
841    scheme can be created then a ``ValueError`` is raised.
842
843    The actual transformation is performed by calling the
844    :meth:`~pyfftw.FFTW.execute` method.
845
846    The arrays can be updated by calling the
847    :meth:`~pyfftw.FFTW.update_arrays` method.
848
849    The created instance of the class is itself callable, and can perform
850    the execution of the FFT, both with or without array updates, returning
851    the result of the FFT. Unlike calling the :meth:`~pyfftw.FFTW.execute`
852    method, calling the class instance will also optionally normalise the
853    output as necessary. Additionally, calling with an input array update
854    will also coerce that array to be the correct dtype.
855
856    See the documentation on the :meth:`~pyfftw.FFTW.__call__` method
857    for more information.
858    '''
859    # Each of these function pointers simply
860    # points to a chosen fftw wrapper function
861    cdef fftw_generic_plan_guru _fftw_planner
862    cdef fftw_generic_execute _fftw_execute
863    cdef fftw_generic_destroy_plan _fftw_destroy
864    cdef fftw_generic_plan_with_nthreads _nthreads_plan_setter
865
866    # The plan is typecast when it is created or used
867    # within the wrapper functions
868    cdef void *_plan
869
870    cdef np.ndarray _input_array
871    cdef np.ndarray _output_array
872    cdef int *_direction
873    cdef unsigned _flags
874
875    cdef bint _simd_allowed
876    cdef int _input_array_alignment
877    cdef int _output_array_alignment
878    cdef bint _use_threads
879
880    cdef object _input_item_strides
881    cdef object _input_strides
882    cdef object _output_item_strides
883    cdef object _output_strides
884    cdef object _input_shape
885    cdef object _output_shape
886    cdef object _input_dtype
887    cdef object _output_dtype
888    cdef object _flags_used
889
890    cdef double _normalisation_scaling
891    cdef double _sqrt_normalisation_scaling
892
893    cdef int _rank
894    cdef _fftw_iodim *_dims
895    cdef int _howmany_rank
896    cdef _fftw_iodim *_howmany_dims
897
898    cdef int64_t *_axes
899    cdef int64_t *_not_axes
900
901    cdef int64_t _total_size
902
903    cdef bint _normalise_idft
904    cdef bint _ortho
905
906    def _get_N(self):
907        '''
908        The product of the lengths of the DFT over all DFT axes.
909        1/N is the normalisation constant. For any input array A,
910        and for any set of axes, 1/N * ifft(fft(A)) = A
911        '''
912        return self._total_size
913
914    N = property(_get_N)
915
916    def _get_simd_aligned(self):
917        '''
918        Return whether or not this FFTW object requires simd aligned
919        input and output data.
920        '''
921        return self._simd_allowed
922
923    simd_aligned = property(_get_simd_aligned)
924
925    def _get_input_alignment(self):
926        '''
927        Returns the byte alignment of the input arrays for which the
928        :class:`~pyfftw.FFTW` object was created.
929
930        Input array updates with arrays that are not aligned on this
931        byte boundary will result in a ValueError being raised, or
932        a copy being made if the :meth:`~pyfftw.FFTW.__call__`
933        interface is used.
934        '''
935        return self._input_array_alignment
936
937    input_alignment = property(_get_input_alignment)
938
939    def _get_output_alignment(self):
940        '''
941        Returns the byte alignment of the output arrays for which the
942        :class:`~pyfftw.FFTW` object was created.
943
944        Output array updates with arrays that are not aligned on this
945        byte boundary will result in a ValueError being raised.
946        '''
947        return self._output_array_alignment
948
949    output_alignment = property(_get_output_alignment)
950
951    def _get_flags_used(self):
952        '''
953        Return which flags were used to construct the FFTW object.
954
955        This includes flags that were added during initialisation.
956        '''
957        return tuple(self._flags_used)
958
959    flags = property(_get_flags_used)
960
961    def _get_input_array(self):
962        '''
963        Return the input array that is associated with the FFTW
964        instance.
965        '''
966        return self._input_array
967
968    input_array = property(_get_input_array)
969
970    def _get_output_array(self):
971        '''
972        Return the output array that is associated with the FFTW
973        instance.
974        '''
975        return self._output_array
976
977    output_array = property(_get_output_array)
978
979    def _get_input_strides(self):
980        '''
981        Return the strides of the input array for which the FFT is planned.
982        '''
983        return self._input_strides
984
985    input_strides = property(_get_input_strides)
986
987    def _get_output_strides(self):
988        '''
989        Return the strides of the output array for which the FFT is planned.
990        '''
991        return self._output_strides
992
993    output_strides = property(_get_output_strides)
994
995    def _get_input_shape(self):
996        '''
997        Return the shape of the input array for which the FFT is planned.
998        '''
999        return self._input_shape
1000
1001    input_shape = property(_get_input_shape)
1002
1003    def _get_output_shape(self):
1004        '''
1005        Return the shape of the output array for which the FFT is planned.
1006        '''
1007        return self._output_shape
1008
1009    output_shape = property(_get_output_shape)
1010
1011    def _get_input_dtype(self):
1012        '''
1013        Return the dtype of the input array for which the FFT is planned.
1014        '''
1015        return self._input_dtype
1016
1017    input_dtype = property(_get_input_dtype)
1018
1019    def _get_output_dtype(self):
1020        '''
1021        Return the shape of the output array for which the FFT is planned.
1022        '''
1023        return self._output_dtype
1024
1025    output_dtype = property(_get_output_dtype)
1026
1027    def _get_direction(self):
1028        '''
1029        Return the planned FFT direction. Either `'FFTW_FORWARD'`,
1030        `'FFTW_BACKWARD'`, or a list of real transform codes of the form
1031        `['FFTW_R*DFT**']`.
1032        '''
1033        cdef int i
1034        transform_directions = list()
1035        if self._direction[0] in [FFTW_FORWARD, FFTW_BACKWARD]:
1036            # It would be nice to return a length-one list here (so that the
1037            # return type is always [str]). This is an annoying type difference,
1038            # but is backwards compatible.
1039            return directions_lookup[self._direction[0]]
1040        else:
1041            for i in range(self._rank):
1042                transform_directions.append(directions_lookup[
1043                        self._direction[i]])
1044        return transform_directions
1045
1046    direction = property(_get_direction)
1047
1048    def _get_axes(self):
1049        '''
1050        Return the axes for the planned FFT in canonical form. That is, as
1051        a tuple of positive integers. The order in which they were passed
1052        is maintained.
1053        '''
1054        axes = []
1055        for i in range(self._rank):
1056            axes.append(self._axes[i])
1057
1058        return tuple(axes)
1059
1060    axes = property(_get_axes)
1061
1062    def _get_normalise_idft(self):
1063        '''
1064        If ``normalise_idft=True``, the inverse transform is scaled by 1/N.
1065        '''
1066        return self._normalise_idft
1067
1068    normalise_idft = property(_get_normalise_idft)
1069
1070    def _get_ortho(self):
1071        '''
1072        If ``ortho=True`` both the forward and inverse transforms are scaled by
1073        1/sqrt(N).
1074        '''
1075        return self._ortho
1076
1077    ortho = property(_get_ortho)
1078
1079    def __cinit__(self, input_array, output_array, axes=(-1,),
1080                  direction='FFTW_FORWARD', flags=('FFTW_MEASURE',),
1081                  unsigned int threads=1, planning_timelimit=None,
1082                  bint normalise_idft=True, bint ortho=False,
1083                  *args, **kwargs):
1084
1085        if isinstance(direction, str):
1086            given_directions = [direction]
1087        else:
1088            given_directions = list(direction)
1089
1090        # Initialise the pointers that need to be freed
1091        self._plan = NULL
1092        self._dims = NULL
1093        self._howmany_dims = NULL
1094
1095        self._axes = NULL
1096        self._not_axes = NULL
1097        self._direction = NULL
1098
1099        self._normalise_idft = normalise_idft
1100        self._ortho = ortho
1101        if self._ortho and self._normalise_idft:
1102            raise ValueError('Invalid options: '
1103                'ortho and normalise_idft cannot both be True.')
1104
1105        flags = list(flags)
1106
1107        cdef double _planning_timelimit
1108        if planning_timelimit is None:
1109            _planning_timelimit = FFTW_NO_TIMELIMIT
1110        else:
1111            try:
1112                _planning_timelimit = planning_timelimit
1113            except TypeError:
1114                raise TypeError('Invalid planning timelimit: '
1115                        'The planning timelimit needs to be a float.')
1116
1117        if not isinstance(input_array, np.ndarray):
1118            raise ValueError('Invalid input array: '
1119                    'The input array needs to be an instance '
1120                    'of numpy.ndarray')
1121
1122        if not isinstance(output_array, np.ndarray):
1123            raise ValueError('Invalid output array: '
1124                    'The output array needs to be an instance '
1125                    'of numpy.ndarray')
1126
1127        try:
1128            input_dtype = input_array.dtype
1129            output_dtype = output_array.dtype
1130            scheme = fftw_schemes[(input_dtype, output_dtype)]
1131        except KeyError:
1132            raise ValueError('Invalid scheme: '
1133                    'The output array and input array dtypes '
1134                    'do not correspond to a valid fftw scheme.')
1135
1136        self._input_dtype = input_dtype
1137        self._output_dtype = output_dtype
1138
1139        functions = scheme_functions(scheme)
1140
1141        self._fftw_planner = planners[functions['planner']]
1142        self._fftw_execute = executors[functions['executor']]
1143        self._fftw_destroy = destroyers[functions['generic_precision']]
1144
1145        self._nthreads_plan_setter = (
1146                nthreads_plan_setters[functions['generic_precision']])
1147
1148        cdef fftw_generic_set_timelimit set_timelimit_func = (
1149                set_timelimit_funcs[functions['generic_precision']])
1150
1151        # We're interested in the natural alignment on the real type, not
1152        # necessarily on the complex type At least one bug was found where
1153        # numpy reported an alignment on a complex dtype that was different
1154        # to that on the real type.
1155        cdef int natural_input_alignment = input_array.real.dtype.alignment
1156        cdef int natural_output_alignment = output_array.real.dtype.alignment
1157
1158        # If either of the arrays is not aligned on a 16-byte boundary,
1159        # we set the FFTW_UNALIGNED flag. This disables SIMD.
1160        # (16 bytes is assumed to be the minimal alignment)
1161        if 'FFTW_UNALIGNED' in flags:
1162            self._simd_allowed = False
1163            self._input_array_alignment = natural_input_alignment
1164            self._output_array_alignment = natural_output_alignment
1165
1166        else:
1167
1168            self._input_array_alignment = -1
1169            self._output_array_alignment = -1
1170
1171            for each_alignment in _valid_simd_alignments:
1172                if (<intptr_t>np.PyArray_DATA(input_array) %
1173                        each_alignment == 0 and
1174                        <intptr_t>np.PyArray_DATA(output_array) %
1175                        each_alignment == 0):
1176
1177                    self._simd_allowed = True
1178
1179                    self._input_array_alignment = each_alignment
1180                    self._output_array_alignment = each_alignment
1181
1182                    break
1183
1184            if (self._input_array_alignment == -1 or
1185                    self._output_array_alignment == -1):
1186
1187                self._simd_allowed = False
1188
1189                self._input_array_alignment = (
1190                        natural_input_alignment)
1191                self._output_array_alignment = (
1192                        natural_output_alignment)
1193                flags.append('FFTW_UNALIGNED')
1194
1195        if (not (<intptr_t>np.PyArray_DATA(input_array)
1196            % self._input_array_alignment == 0)):
1197            raise ValueError('Invalid input alignment: '
1198                    'The input array is expected to lie on a %d '
1199                    'byte boundary.' % self._input_array_alignment)
1200
1201        if (not (<intptr_t>np.PyArray_DATA(output_array)
1202            % self._output_array_alignment == 0)):
1203            raise ValueError('Invalid output alignment: '
1204                    'The output array is expected to lie on a %d '
1205                    'byte boundary.' % self._output_array_alignment)
1206
1207        for direction in given_directions:
1208            if direction not in scheme_directions[scheme]:
1209                raise ValueError('Invalid direction: '
1210                        'The direction is not valid for the scheme. '
1211                        'Try setting it explicitly if it is not already.')
1212
1213        self._direction = <int *>malloc(len(axes)*sizeof(int))
1214
1215        real_transforms = True
1216        cdef int i
1217        if given_directions[0] in ['FFTW_FORWARD', 'FFTW_BACKWARD']:
1218            self._direction[0] = directions[given_directions[0]]
1219            real_transforms = False
1220        else:
1221            if len(axes) != len(given_directions):
1222                raise ValueError('For real-to-real transforms, there must '
1223                        'be exactly one specified transform for each '
1224                        'transformed axis.')
1225            for i in range(len(axes)):
1226                if given_directions[0] in ['FFTW_FORWARD', 'FFTW_BACKWARD']:
1227                    raise ValueError('Heterogeneous transforms cannot be '
1228                            'assigned with \'FFTW_FORWARD\' or '
1229                            '\'FFTW_BACKWARD\'.')
1230                else:
1231                    self._direction[i] = directions[given_directions[i]]
1232
1233        self._input_shape = input_array.shape
1234        self._output_shape = output_array.shape
1235
1236        self._input_array = input_array
1237        self._output_array = output_array
1238
1239        self._axes = <int64_t *>malloc(len(axes)*sizeof(int64_t))
1240        for n in range(len(axes)):
1241            self._axes[n] = axes[n]
1242
1243        # Set the negative entries to their actual index (use the size
1244        # of the shape array for this)
1245        cdef int64_t array_dimension = len(self._input_shape)
1246
1247        for n in range(len(axes)):
1248            if self._axes[n] < 0:
1249                self._axes[n] = self._axes[n] + array_dimension
1250
1251            if self._axes[n] >= array_dimension or self._axes[n] < 0:
1252                raise IndexError('Invalid axes: '
1253                    'The axes list cannot contain invalid axes.')
1254
1255        cdef int64_t unique_axes_length
1256        cdef int64_t *unique_axes
1257        cdef int64_t *not_axes
1258
1259        make_axes_unique(self._axes, len(axes), &unique_axes,
1260                &not_axes, array_dimension, &unique_axes_length)
1261
1262        # and assign axes and not_axes to the filled arrays
1263        free(self._axes)
1264        self._axes = unique_axes
1265        self._not_axes = not_axes
1266
1267        total_N = 1
1268        for n in range(unique_axes_length):
1269            if self._input_shape[self._axes[n]] == 0:
1270                raise ValueError('Zero length array: '
1271                    'The input array should have no zero length'
1272                    'axes over which the FFT is to be taken')
1273
1274            if real_transforms:
1275                if self._direction[n] == FFTW_RODFT00:
1276                    total_N *= 2*(self._input_shape[self._axes[n]] + 1)
1277                elif self._direction[n] == FFTW_REDFT00:
1278                    if (self._input_shape[self._axes[n]] < 2):
1279                        raise ValueError('FFTW_REDFT00 (also known as DCT-1) is'
1280                                ' not defined for inputs of length less than two.')
1281                    total_N *= 2*(self._input_shape[self._axes[n]] - 1)
1282                else:
1283                    total_N *= 2*self._input_shape[self._axes[n]]
1284            else:
1285                if self._direction[0] == FFTW_FORWARD:
1286                    total_N *= self._input_shape[self._axes[n]]
1287                else:
1288                    total_N *= self._output_shape[self._axes[n]]
1289
1290        self._total_size = total_N
1291        self._normalisation_scaling = 1/float(self.N)
1292        self._sqrt_normalisation_scaling = np.sqrt(self._normalisation_scaling)
1293
1294        # Now we can validate the array shapes
1295        cdef validator _validator
1296
1297        if functions['validator'] == -1:
1298            if not (output_array.shape == input_array.shape):
1299                raise ValueError('Invalid shapes: '
1300                        'The output array should be the same shape as the '
1301                        'input array for the given array dtypes.')
1302        else:
1303            _validator = validators[functions['validator']]
1304            if not _validator(input_array, output_array,
1305                    self._axes, self._not_axes, unique_axes_length):
1306                raise ValueError('Invalid shapes: '
1307                        'The input array and output array are invalid '
1308                        'complementary shapes for their dtypes.')
1309
1310        self._rank = unique_axes_length
1311        self._howmany_rank = self._input_array.ndim - unique_axes_length
1312
1313        self._flags = 0
1314        self._flags_used = []
1315        for each_flag in flags:
1316            try:
1317                self._flags |= flag_dict[each_flag]
1318                self._flags_used.append(each_flag)
1319            except KeyError:
1320                raise ValueError('Invalid flag: ' + '\'' +
1321                        each_flag + '\' is not a valid planner flag.')
1322
1323
1324        if ('FFTW_DESTROY_INPUT' not in flags) and (
1325                (scheme[0] != 'c2r') or not self._rank > 1):
1326            # The default in all possible cases is to preserve the input
1327            # This is not possible for r2c arrays with rank > 1
1328            self._flags |= FFTW_PRESERVE_INPUT
1329
1330        # Set up the arrays of structs for holding the stride shape
1331        # information
1332        self._dims = <_fftw_iodim *>malloc(
1333                self._rank * sizeof(_fftw_iodim))
1334        self._howmany_dims = <_fftw_iodim *>malloc(
1335                self._howmany_rank * sizeof(_fftw_iodim))
1336
1337        if self._dims == NULL or self._howmany_dims == NULL:
1338            # Not much else to do than raise an exception
1339            raise MemoryError
1340
1341        # Find the strides for all the axes of both arrays in terms of the
1342        # number of items (as opposed to the number of bytes).
1343        self._input_strides = input_array.strides
1344        self._input_item_strides = tuple([stride/input_array.itemsize
1345            for stride in input_array.strides])
1346        self._output_strides = output_array.strides
1347        self._output_item_strides = tuple([stride/output_array.itemsize
1348            for stride in output_array.strides])
1349
1350        # Make sure that the arrays are not too big for fftw
1351        # This is hard to test, so we cross our fingers and hope for the
1352        # best (any suggestions, please get in touch).
1353        for i in range(0, len(self._input_shape)):
1354            if self._input_shape[i] >= <Py_ssize_t> limits.INT_MAX:
1355                raise ValueError('Dimensions of the input array must be ' +
1356                        'less than ', str(limits.INT_MAX))
1357
1358            if self._input_item_strides[i] >= <Py_ssize_t> limits.INT_MAX:
1359                raise ValueError('Strides of the input array must be ' +
1360                        'less than ', str(limits.INT_MAX))
1361
1362        for i in range(0, len(self._output_shape)):
1363            if self._output_shape[i] >= <Py_ssize_t> limits.INT_MAX:
1364                raise ValueError('Dimensions of the output array must be ' +
1365                        'less than ', str(limits.INT_MAX))
1366
1367            if self._output_item_strides[i] >= <Py_ssize_t> limits.INT_MAX:
1368                raise ValueError('Strides of the output array must be ' +
1369                        'less than ', str(limits.INT_MAX))
1370
1371        fft_shape_lookup = functions['fft_shape_lookup']
1372        if fft_shape_lookup == -1:
1373            fft_shape = self._input_shape
1374        else:
1375            fft_shape = fft_shape_lookup(input_array, output_array)
1376
1377        # Fill in the stride and shape information
1378        input_strides_array = self._input_item_strides
1379        output_strides_array = self._output_item_strides
1380        for i in range(0, self._rank):
1381            self._dims[i]._n = fft_shape[self._axes[i]]
1382            self._dims[i]._is = input_strides_array[self._axes[i]]
1383            self._dims[i]._os = output_strides_array[self._axes[i]]
1384
1385        for i in range(0, self._howmany_rank):
1386            self._howmany_dims[i]._n = fft_shape[self._not_axes[i]]
1387            self._howmany_dims[i]._is = input_strides_array[self._not_axes[i]]
1388            self._howmany_dims[i]._os = output_strides_array[self._not_axes[i]]
1389
1390        # parallel execution
1391        self._use_threads = (threads > 1)
1392
1393        ## Point at which FFTW calls are made
1394        ## (and none should be made before this)
1395
1396        # noop if threads library not available
1397        self._nthreads_plan_setter(threads)
1398
1399        # Set the timelimit
1400        set_timelimit_func(_planning_timelimit)
1401
1402        # Finally, construct the plan, after acquiring the global planner lock
1403        # (so that only one python thread can plan at a time, as the FFTW
1404        # planning functions are not thread-safe)
1405
1406        # no self-lookups allowed in nogil block, so must grab all these first
1407        cdef void *plan
1408        cdef fftw_generic_plan_guru fftw_planner = self._fftw_planner
1409        cdef int rank = self._rank
1410        cdef fftw_iodim *dims = <fftw_iodim *>self._dims
1411        cdef int howmany_rank = self._howmany_rank
1412        cdef fftw_iodim *howmany_dims = <fftw_iodim *>self._howmany_dims
1413        cdef void *_in = <void *>np.PyArray_DATA(self._input_array)
1414        cdef void *_out = <void *>np.PyArray_DATA(self._output_array)
1415        cdef unsigned c_flags = self._flags
1416
1417        with plan_lock, nogil:
1418            plan = fftw_planner(rank, dims, howmany_rank, howmany_dims,
1419                                _in, _out, self._direction, c_flags)
1420        self._plan = plan
1421
1422        if self._plan == NULL:
1423            if 'FFTW_WISDOM_ONLY' in flags:
1424                raise RuntimeError('No FFTW wisdom is known for this plan.')
1425            else:
1426                raise RuntimeError('The data has an uncaught error that led '+
1427                    'to the planner returning NULL. This is a bug.')
1428
1429    def __init__(self, input_array, output_array, axes=(-1,),
1430            direction='FFTW_FORWARD', flags=('FFTW_MEASURE',),
1431            int threads=1, planning_timelimit=None,
1432            normalise_idft=True, ortho=False):
1433        '''
1434        **Arguments**:
1435
1436        * ``input_array`` and ``output_array`` should be numpy arrays.
1437          The contents of these arrays will be destroyed by the planning
1438          process during initialisation. Information on supported
1439          dtypes for the arrays is :ref:`given below <scheme_table>`.
1440
1441        * ``axes`` describes along which axes the DFT should be taken.
1442          This should be a valid list of axes. Repeated axes are
1443          only transformed once. Invalid axes will raise an ``IndexError``
1444          exception. This argument is equivalent to the same
1445          argument in :func:`numpy.fft.fftn`, except for the fact that
1446          the behaviour of repeated axes is different (``numpy.fft``
1447          will happily take the fft of the same axis if it is repeated
1448          in the ``axes`` argument). Rudimentary testing has suggested
1449          this is down to the underlying FFTW library and so unlikely
1450          to be fixed in these wrappers.
1451
1452        * The ``direction`` parameter describes what sort of
1453          transformation the object should compute. This parameter is
1454          poorly named for historical reasons: older versions of pyFFTW
1455          only supported forward and backward transformations, for which
1456          this name made sense. Since then pyFFTW has been expanded to
1457          support real to real transforms as well and the name is not
1458          quite as descriptive.
1459
1460          ``direction`` should either be a string, or, in the case of
1461          multiple real transforms, a list of strings. The two values
1462          corresponding to the DFT are
1463
1464          * ``'FFTW_FORWARD'``, which is the forward discrete Fourier
1465            transform, and
1466          * ``'FFTW_BACKWARD'``, which is the backward discrete Fourier
1467            transform.
1468
1469          Note that, for the two above options, only the Complex schemes
1470          allow a free choice for ``direction``. The direction *must*
1471          agree with the the :ref:`table below <scheme_table>` if a Real
1472          scheme is used, otherwise a ``ValueError`` is raised.
1473
1474
1475          Alternatively, if you are interested in one of the real to real
1476          transforms, then pyFFTW supports four different discrete cosine
1477          transforms:
1478
1479          * ``'FFTW_REDFT00'``,
1480          * ``'FFTW_REDFT01'``,
1481          * ``'FFTW_REDFT10'``, and
1482          * ``'FFTW_REDFT01'``,
1483
1484          and four discrete sine transforms:
1485
1486          * ``'FFTW_RODFT00'``,
1487          * ``'FFTW_RODFT01'``,
1488          * ``'FFTW_RODFT10'``, and
1489          * ``'FFTW_RODFT01'``.
1490
1491          pyFFTW uses the same naming convention for these flags as FFTW:
1492          the ``'REDFT'`` part of the name is an acronym for 'real even
1493          discrete Fourier transform, and, similarly, ``'RODFT'`` stands
1494          for 'real odd discrete Fourier transform'. The trailing ``'0'``
1495          is notation for even data (in terms of symmetry) and the
1496          trailing ``'1'`` is for odd data.
1497
1498          Unlike the plain discrete Fourier transform, one may specify a
1499          different real to real transformation over each axis: for example,
1500
1501          .. code-block:: none
1502             a = pyfftw.empty_aligned((128,128,128))
1503             b = pyfftw.empty_aligned((128,128,128))
1504             directions = ['FFTW_REDFT00', 'FFTW_RODFT11']
1505             transform = pyfftw.FFTW(a, b, axes=(0, 2), direction=directions)
1506
1507          will create a transformation across the first and last axes
1508          with a discrete cosine transform over the first and a discrete
1509          sine transform over the last.
1510
1511          Unfortunately, since this class is ultimately just a wrapper
1512          for various transforms implemented in FFTW, one cannot combine
1513          real transformations with real to complex transformations in a
1514          single object.
1515
1516        .. _FFTW_flags:
1517
1518        * ``flags`` is a list of strings and is a subset of the
1519          flags that FFTW allows for the planners:
1520
1521          * ``'FFTW_ESTIMATE'``, ``'FFTW_MEASURE'``, ``'FFTW_PATIENT'`` and
1522            ``'FFTW_EXHAUSTIVE'`` are supported. These describe the
1523            increasing amount of effort spent during the planning
1524            stage to create the fastest possible transform.
1525            Usually ``'FFTW_MEASURE'`` is a good compromise. If no flag
1526            is passed, the default ``'FFTW_MEASURE'`` is used.
1527          * ``'FFTW_UNALIGNED'`` is supported.
1528            This tells FFTW not to assume anything about the
1529            alignment of the data and disabling any SIMD capability
1530            (see below).
1531          * ``'FFTW_DESTROY_INPUT'`` is supported.
1532            This tells FFTW that the input array can be destroyed during
1533            the transform, sometimes allowing a faster algorithm to be
1534            used. The default behaviour is, if possible, to preserve the
1535            input. In the case of the 1D Backwards Real transform, this
1536            may result in a performance hit. In the case of a backwards
1537            real transform for greater than one dimension, it is not
1538            possible to preserve the input, making this flag implicit
1539            in that case. A little more on this is given
1540            :ref:`below<scheme_table>`.
1541          * ``'FFTW_WISDOM_ONLY'`` is supported.
1542            This tells FFTW to raise an error if no plan for this transform
1543            and data type is already in the wisdom. It thus provides a method
1544            to determine whether planning would require additional effort or the
1545            cached wisdom can be used. This flag should be combined with the
1546            various planning-effort flags (``'FFTW_ESTIMATE'``,
1547            ``'FFTW_MEASURE'``, etc.); if so, then an error will be raised if
1548            wisdom derived from that level of planning effort (or higher) is
1549            not present. If no planning-effort flag is used, the default of
1550            ``'FFTW_ESTIMATE'`` is assumed.
1551            Note that wisdom is specific to all the parameters, including the
1552            data alignment. That is, if wisdom was generated with input/output
1553            arrays with one specific alignment, using ``'FFTW_WISDOM_ONLY'``
1554            to create a plan for arrays with any different alignment will
1555            cause the ``'FFTW_WISDOM_ONLY'`` planning to fail. Thus it is
1556            important to specifically control the data alignment to make the
1557            best use of ``'FFTW_WISDOM_ONLY'``.
1558
1559          The `FFTW planner flags documentation
1560          <http://www.fftw.org/fftw3_doc/Planner-Flags.html#Planner-Flags>`_
1561          has more information about the various flags and their impact.
1562          Note that only the flags documented here are supported.
1563
1564        * ``threads`` tells the wrapper how many threads to use
1565          when invoking FFTW, with a default of 1. If the number
1566          of threads is greater than 1, then the GIL is released
1567          by necessity.
1568
1569        * ``planning_timelimit`` is a floating point number that
1570          indicates to the underlying FFTW planner the maximum number of
1571          seconds it should spend planning the FFT. This is a rough
1572          estimate and corresponds to calling of ``fftw_set_timelimit()``
1573          (or an equivalent dependent on type) in the underlying FFTW
1574          library. If ``None`` is set, the planner will run indefinitely
1575          until all the planning modes allowed by the flags have been
1576          tried. See the `FFTW planner flags page
1577          <http://www.fftw.org/fftw3_doc/Planner-Flags.html#Planner-Flags>`_
1578          for more information on this.
1579
1580        .. _fftw_schemes:
1581
1582        **Schemes**
1583
1584        The currently supported full (so not discrete sine or discrete
1585        cosine) DFT schemes are as follows:
1586
1587        .. _scheme_table:
1588
1589        +----------------+-----------------------+------------------------+-----------+
1590        | Type           | ``input_array.dtype`` | ``output_array.dtype`` | Direction |
1591        +================+=======================+========================+===========+
1592        | Complex        | ``complex64``         | ``complex64``          | Both      |
1593        +----------------+-----------------------+------------------------+-----------+
1594        | Complex        | ``complex128``        | ``complex128``         | Both      |
1595        +----------------+-----------------------+------------------------+-----------+
1596        | Complex        | ``clongdouble``       | ``clongdouble``        | Both      |
1597        +----------------+-----------------------+------------------------+-----------+
1598        | Real           | ``float32``           | ``complex64``          | Forwards  |
1599        +----------------+-----------------------+------------------------+-----------+
1600        | Real           | ``float64``           | ``complex128``         | Forwards  |
1601        +----------------+-----------------------+------------------------+-----------+
1602        | Real           | ``longdouble``        | ``clongdouble``        | Forwards  |
1603        +----------------+-----------------------+------------------------+-----------+
1604        | Real\ :sup:`1` | ``complex64``         | ``float32``            | Backwards |
1605        +----------------+-----------------------+------------------------+-----------+
1606        | Real\ :sup:`1` | ``complex128``        | ``float64``            | Backwards |
1607        +----------------+-----------------------+------------------------+-----------+
1608        | Real\ :sup:`1` | ``clongdouble``       | ``longdouble``         | Backwards |
1609        +----------------+-----------------------+------------------------+-----------+
1610
1611        \ :sup:`1`  Note that the Backwards Real transform for the case
1612        in which the dimensionality of the transform is greater than 1
1613        will destroy the input array. This is inherent to FFTW and the only
1614        general work-around for this is to copy the array prior to
1615        performing the transform. In the case where the dimensionality
1616        of the transform is 1, the default is to preserve the input array.
1617        This is different from the default in the underlying library, and
1618        some speed gain may be achieved by allowing the input array to
1619        be destroyed by passing the ``'FFTW_DESTROY_INPUT'``
1620        :ref:`flag <FFTW_flags>`.
1621
1622        The discrete sine and discrete cosine transforms are supported
1623        for all three real types.
1624
1625        ``clongdouble`` typically maps directly to ``complex256``
1626        or ``complex192``, and ``longdouble`` to ``float128`` or
1627        ``float96``, dependent on platform.
1628
1629        The relative shapes of the arrays should be as follows:
1630
1631        * For a Complex transform, ``output_array.shape == input_array.shape``
1632        * For a Real transform in the Forwards direction, both the following
1633          should be true:
1634
1635          * ``output_array.shape[axes][-1] == input_array.shape[axes][-1]//2 + 1``
1636          * All the other axes should be equal in length.
1637
1638        * For a Real transform in the Backwards direction, both the following
1639          should be true:
1640
1641          * ``input_array.shape[axes][-1] == output_array.shape[axes][-1]//2 + 1``
1642          * All the other axes should be equal in length.
1643
1644        In the above expressions for the Real transform, the ``axes``
1645        arguments denotes the unique set of axes on which we are taking
1646        the FFT, in the order passed. It is the last of these axes that
1647        is subject to the special case shown.
1648
1649        The shapes for the real transforms corresponds to those
1650        stipulated by the FFTW library. Further information can be
1651        found in the FFTW documentation on the `real DFT
1652        <http://www.fftw.org/fftw3_doc/Guru-Real_002ddata-DFTs.html>`_.
1653
1654        The actual arrangement in memory is arbitrary and the scheme
1655        can be planned for any set of strides on either the input
1656        or the output. The user should not have to worry about this
1657        and any valid numpy array should work just fine.
1658
1659        What is calculated is exactly what FFTW calculates.
1660        Notably, this is an unnormalized transform so should
1661        be scaled as necessary (fft followed by ifft will scale
1662        the input by N, the product of the dimensions along which
1663        the DFT is taken). For further information, see the
1664        `FFTW documentation
1665        <http://www.fftw.org/fftw3_doc/What-FFTW-Really-Computes.html>`_.
1666
1667        The FFTW library benefits greatly from the beginning of each
1668        DFT axes being aligned on the correct byte boundary, enabling
1669        SIMD instructions. By default, if the data begins on such a
1670        boundary, then FFTW will be allowed to try and enable
1671        SIMD instructions. This means that all future changes to
1672        the data arrays will be checked for similar alignment. SIMD
1673        instructions can be explicitly disabled by setting the
1674        FFTW_UNALIGNED flags, to allow for updates with unaligned
1675        data.
1676
1677        :func:`~pyfftw.byte_align` and
1678        :func:`~pyfftw.empty_aligned` are two methods
1679        included with this module for producing aligned arrays.
1680
1681        The optimum alignment for the running platform is provided
1682        by :data:`pyfftw.simd_alignment`, though a different alignment
1683        may still result in some performance improvement. For example,
1684        if the processor supports AVX (requiring 32-byte alignment) as
1685        well as SSE (requiring 16-byte alignment), then if the array
1686        is 16-byte aligned, SSE will still be used.
1687
1688        It's worth noting that just being aligned may not be sufficient
1689        to create the fastest possible transform. For example, if the
1690        array is not contiguous (i.e. certain axes are displaced in
1691        memory), it may be faster to plan a transform for a contiguous
1692        array, and then rely on the array being copied in before the
1693        transform (which :class:`pyfftw.FFTW` will handle for you when
1694        accessed through :meth:`~pyfftw.FFTW.__call__`).
1695        '''
1696
1697    def __dealloc__(self):
1698
1699        if not self._axes == NULL:
1700            free(self._axes)
1701
1702        if not self._not_axes == NULL:
1703            free(self._not_axes)
1704
1705        if not self._plan == NULL:
1706            self._fftw_destroy(self._plan)
1707
1708        if not self._dims == NULL:
1709            free(self._dims)
1710
1711        if not self._howmany_dims == NULL:
1712            free(self._howmany_dims)
1713
1714        if not self._direction == NULL:
1715            free(self._direction)
1716
1717    def __call__(self, input_array=None, output_array=None,
1718            normalise_idft=None, ortho=None):
1719        '''__call__(input_array=None, output_array=None, normalise_idft=True,
1720                    ortho=False)
1721
1722        Calling the class instance (optionally) updates the arrays, then
1723        calls :meth:`~pyfftw.FFTW.execute`, before optionally normalising
1724        the output and returning the output array.
1725
1726        It has some built-in helpers to make life simpler for the calling
1727        functions (as distinct from manually updating the arrays and
1728        calling :meth:`~pyfftw.FFTW.execute`).
1729
1730        If ``normalise_idft`` is ``True`` (the default), then the output from
1731        an inverse DFT (i.e. when the direction flag is ``'FFTW_BACKWARD'``) is
1732        scaled by 1/N, where N is the product of the lengths of input array on
1733        which the FFT is taken. If the direction is ``'FFTW_FORWARD'``, this
1734        flag makes no difference to the output array.
1735
1736        If ``ortho`` is ``True``, then the output of both forward
1737        and inverse DFT operations is scaled by 1/sqrt(N), where N is the
1738        product of the lengths of input array on which the FFT is taken.  This
1739        ensures that the DFT is a unitary operation, meaning that it satisfies
1740        Parseval's theorem (the sum of the squared values of the transform
1741        output is equal to the sum of the squared values of the input).  In
1742        other words, the energy of the signal is preserved.
1743
1744        If either ``normalise_idft`` or ``ortho`` are ``True``, then
1745        ifft(fft(A)) = A.
1746
1747        When ``input_array`` is something other than None, then the passed in
1748        array is coerced to be the same dtype as the input array used when the
1749        class was instantiated, the byte-alignment of the passed in array is
1750        made consistent with the expected byte-alignment and the striding is
1751        made consistent with the expected striding. All this may, but not
1752        necessarily, require a copy to be made.
1753
1754        As noted in the :ref:`scheme table<scheme_table>`, if the FFTW
1755        instance describes a backwards real transform of more than one
1756        dimension, the contents of the input array will be destroyed. It is
1757        up to the calling function to make a copy if it is necessary to
1758        maintain the input array.
1759
1760        ``output_array`` is always used as-is if possible. If the dtype, the
1761        alignment or the striding is incorrect for the FFTW object, then a
1762        ``ValueError`` is raised.
1763
1764        The coerced input array and the output array (as appropriate) are
1765        then passed as arguments to
1766        :meth:`~pyfftw.FFTW.update_arrays`, after which
1767        :meth:`~pyfftw.FFTW.execute` is called, and then normalisation
1768        is applied to the output array if that is desired.
1769
1770        Note that it is possible to pass some data structure that can be
1771        converted to an array, such as a list, so long as it fits the data
1772        requirements of the class instance, such as array shape.
1773
1774        Other than the dtype and the alignment of the passed in arrays, the
1775        rest of the requirements on the arrays mandated by
1776        :meth:`~pyfftw.FFTW.update_arrays` are enforced.
1777
1778        A ``None`` argument to either keyword means that that array is not
1779        updated.
1780
1781        The result of the FFT is returned. This is the same array that is used
1782        internally and will be overwritten again on subsequent calls. If you
1783        need the data to persist longer than a subsequent call, you should
1784        copy the returned array.
1785        '''
1786
1787        if ortho is None:
1788            ortho = self._ortho
1789        if normalise_idft is None:
1790            normalise_idft = self._normalise_idft
1791
1792        if ortho and normalise_idft:
1793            raise ValueError('Invalid options: ortho and normalise_idft cannot'
1794                             ' both be True.')
1795
1796        if input_array is not None or output_array is not None:
1797
1798            if input_array is None:
1799                input_array = self._input_array
1800
1801            if output_array is None:
1802                output_array = self._output_array
1803
1804            if not isinstance(input_array, np.ndarray):
1805                copy_needed = True
1806            elif (not input_array.dtype == self._input_dtype):
1807                copy_needed = True
1808            elif (not input_array.strides == self._input_strides):
1809                copy_needed = True
1810            elif not (<intptr_t>np.PyArray_DATA(input_array)
1811                    % self.input_alignment == 0):
1812                copy_needed = True
1813            else:
1814                copy_needed = False
1815
1816            if copy_needed:
1817
1818                if not isinstance(input_array, np.ndarray):
1819                    input_array = np.asanyarray(input_array)
1820
1821                if not input_array.shape == self._input_shape:
1822                    raise ValueError('Invalid input shape: '
1823                            'The new input array should be the same shape '
1824                            'as the input array used to instantiate the '
1825                            'object.')
1826
1827                self._input_array[:] = input_array
1828
1829                if output_array is not None:
1830                    # No point wasting time if no update is necessary
1831                    # (which the copy above may have avoided)
1832                    input_array = self._input_array
1833                    self.update_arrays(input_array, output_array)
1834
1835            else:
1836                self.update_arrays(input_array, output_array)
1837
1838        self.execute()
1839
1840        # after executing, optionally normalize output array
1841        if ortho:
1842            self._output_array *= self._sqrt_normalisation_scaling
1843        elif normalise_idft and self._direction[0] == FFTW_BACKWARD:
1844            self._output_array *= self._normalisation_scaling
1845        elif not normalise_idft and self._direction[0] == FFTW_FORWARD:
1846            self._output_array *= self._normalisation_scaling
1847
1848        return self._output_array
1849
1850    cpdef update_arrays(self,
1851            new_input_array, new_output_array):
1852        '''update_arrays(new_input_array, new_output_array)
1853
1854        Update the arrays upon which the DFT is taken.
1855
1856        The new arrays should be of the same dtypes as the originals, the same
1857        shapes as the originals and should have the same strides between axes.
1858        If the original data was aligned so as to allow SIMD instructions
1859        (e.g. by being aligned on a 16-byte boundary), then the new array must
1860        also be aligned so as to allow SIMD instructions (assuming, of
1861        course, that the ``FFTW_UNALIGNED`` flag was not enabled).
1862
1863        The byte alignment requirement extends to requiring natural
1864        alignment in the non-SIMD cases as well, but this is much less
1865        stringent as it simply means avoiding arrays shifted by, say,
1866        a single byte (which invariably takes some effort to
1867        achieve!).
1868
1869        If all these conditions are not met, a ``ValueError`` will
1870        be raised and the data will *not* be updated (though the
1871        object will still be in a sane state).
1872        '''
1873        if not isinstance(new_input_array, np.ndarray):
1874            raise ValueError('Invalid input array: '
1875                    'The new input array needs to be an instance '
1876                    'of numpy.ndarray')
1877
1878        if not isinstance(new_output_array, np.ndarray):
1879            raise ValueError('Invalid output array '
1880                    'The new output array needs to be an instance '
1881                    'of numpy.ndarray')
1882
1883        if not (<intptr_t>np.PyArray_DATA(new_input_array) %
1884                self.input_alignment == 0):
1885            raise ValueError('Invalid input alignment: '
1886                    'The original arrays were %d-byte aligned. It is '
1887                    'necessary that the update input array is similarly '
1888                    'aligned.' % self.input_alignment)
1889
1890        if not (<intptr_t>np.PyArray_DATA(new_output_array) %
1891                self.output_alignment == 0):
1892            raise ValueError('Invalid output alignment: '
1893                    'The original arrays were %d-byte aligned. It is '
1894                    'necessary that the update output array is similarly '
1895                    'aligned.' % self.output_alignment)
1896
1897        if not new_input_array.dtype == self._input_dtype:
1898            raise ValueError('Invalid input dtype: '
1899                    'The new input array is not of the same '
1900                    'dtype as was originally planned for.')
1901
1902        if not new_output_array.dtype == self._output_dtype:
1903            raise ValueError('Invalid output dtype: '
1904                    'The new output array is not of the same '
1905                    'dtype as was originally planned for.')
1906
1907        new_input_shape = new_input_array.shape
1908        new_output_shape = new_output_array.shape
1909
1910        new_input_strides = new_input_array.strides
1911        new_output_strides = new_output_array.strides
1912
1913        if not new_input_shape == self._input_shape:
1914            raise ValueError('Invalid input shape: '
1915                    'The new input array should be the same shape as '
1916                    'the input array used to instantiate the object.')
1917
1918        if not new_output_shape == self._output_shape:
1919            raise ValueError('Invalid output shape: '
1920                    'The new output array should be the same shape as '
1921                    'the output array used to instantiate the object.')
1922
1923        if not new_input_strides == self._input_strides:
1924            raise ValueError('Invalid input striding: '
1925                    'The strides should be identical for the new '
1926                    'input array as for the old.')
1927
1928        if not new_output_strides == self._output_strides:
1929            raise ValueError('Invalid output striding: '
1930                    'The strides should be identical for the new '
1931                    'output array as for the old.')
1932
1933        self._update_arrays(new_input_array, new_output_array)
1934
1935    cdef _update_arrays(self,
1936            np.ndarray new_input_array, np.ndarray new_output_array):
1937        ''' A C interface to the update_arrays method that does not
1938        perform any checks on strides being correct and so on.
1939        '''
1940        self._input_array = new_input_array
1941        self._output_array = new_output_array
1942
1943    def get_input_array(self):
1944        '''get_input_array()
1945
1946        Return the input array that is associated with the FFTW
1947        instance.
1948
1949        *Deprecated since 0.10. Consider using the* :attr:`FFTW.input_array`
1950        *property instead.*
1951        '''
1952        warnings.warn('get_input_array is deprecated. '
1953                'Consider using the input_array property instead.',
1954                DeprecationWarning)
1955
1956        return self._input_array
1957
1958    def get_output_array(self):
1959        '''get_output_array()
1960
1961        Return the output array that is associated with the FFTW
1962        instance.
1963
1964        *Deprecated since 0.10. Consider using the* :attr:`FFTW.output_array`
1965        *property instead.*
1966        '''
1967        warnings.warn('get_output_array is deprecated. '
1968                'Consider using the output_array property instead.',
1969                DeprecationWarning)
1970
1971        return self._output_array
1972
1973    cpdef execute(self):
1974        '''execute()
1975
1976        Execute the planned operation, taking the correct kind of FFT of
1977        the input array (i.e. :attr:`FFTW.input_array`),
1978        and putting the result in the output array (i.e.
1979        :attr:`FFTW.output_array`).
1980        '''
1981        cdef void *input_pointer = (
1982                <void *>np.PyArray_DATA(self._input_array))
1983        cdef void *output_pointer = (
1984                <void *>np.PyArray_DATA(self._output_array))
1985
1986        cdef void *plan = self._plan
1987        cdef fftw_generic_execute fftw_execute = self._fftw_execute
1988        with nogil:
1989            fftw_execute(plan, input_pointer, output_pointer)
1990
1991cdef void count_char(char c, void *counter_ptr):
1992    '''
1993    On every call, increment the derefenced counter_ptr.
1994    '''
1995    (<int *>counter_ptr)[0] += 1
1996
1997
1998cdef void write_char_to_string(char c, void *string_location_ptr):
1999    '''
2000    Write the passed character c to the memory location
2001    pointed to by the contents of string_location_ptr (i.e. a pointer
2002    to a pointer), then increment the contents of string_location_ptr
2003    (i.e. move to the next byte in memory).
2004
2005    In other words, for every character that is passed, we write that
2006    to a string that is referenced by the dereferenced value of
2007    string_location_ptr.
2008
2009    If the derefenced value of string_location points to an
2010    unallocated piece of memory, a segfault will likely occur.
2011    '''
2012    cdef char *write_location = <char *>((<intptr_t *>string_location_ptr)[0])
2013    write_location[0] = c
2014
2015    (<intptr_t *>string_location_ptr)[0] += 1
2016
2017
2018def export_wisdom():
2019    '''export_wisdom()
2020
2021    Return the FFTW wisdom as a tuple of strings.
2022
2023    The first string in the tuple is the string for the double precision
2024    wisdom, the second is for single precision, and the third for long double
2025    precision. If any of the precisions is not supported in the build, the
2026    string is empty.
2027
2028    The tuple that is returned from this function can be used as the argument
2029    to :func:`~pyfftw.import_wisdom`.
2030
2031    '''
2032
2033    cdef:
2034        # can't directly initialize `bytes` with ''
2035        const char* empty = ''
2036        bytes py_wisdom  = empty
2037        bytes py_wisdomf = empty
2038        bytes py_wisdoml = empty
2039
2040        # default init to zero
2041        cdef int counter  = 0
2042        cdef int counterf = 0
2043        cdef int counterl = 0
2044
2045        char* c_wisdom  = NULL
2046        char* c_wisdomf = NULL
2047        char* c_wisdoml = NULL
2048
2049    # count the length of the string and extract it manually rather than using
2050    # `fftw_export_wisdom_to_string` to avoid calling `free` on the string
2051    # potentially allocated by a different C library; see #3
2052    IF HAVE_DOUBLE:
2053        fftw_export_wisdom(&count_char, <void *>&counter)
2054        c_wisdom = <char *>malloc(sizeof(char)*(counter + 1))
2055        if c_wisdom == NULL:
2056            raise MemoryError
2057        # Set the pointers to the string pointers
2058        cdef intptr_t c_wisdom_ptr = <intptr_t>c_wisdom
2059        fftw_export_wisdom(&write_char_to_string, <void *>&c_wisdom_ptr)
2060        # Write the last byte as the null byte
2061        c_wisdom[counter] = 0
2062        try:
2063            py_wisdom = c_wisdom
2064        finally:
2065            free(c_wisdom)
2066    IF HAVE_SINGLE:
2067        fftwf_export_wisdom(&count_char, <void *>&counterf)
2068        c_wisdomf = <char *>malloc(sizeof(char)*(counterf + 1))
2069        if c_wisdomf == NULL:
2070            raise MemoryError
2071        cdef intptr_t c_wisdomf_ptr = <intptr_t>c_wisdomf
2072        fftwf_export_wisdom(&write_char_to_string, <void *>&c_wisdomf_ptr)
2073        c_wisdomf[counterf] = 0
2074        try:
2075            py_wisdomf = c_wisdomf
2076        finally:
2077            free(c_wisdomf)
2078    IF HAVE_LONG:
2079        fftwl_export_wisdom(&count_char, <void *>&counterl)
2080        c_wisdoml = <char *>malloc(sizeof(char)*(counterl + 1))
2081        if c_wisdoml == NULL:
2082            raise MemoryError
2083        cdef intptr_t c_wisdoml_ptr = <intptr_t>c_wisdoml
2084        fftwl_export_wisdom(&write_char_to_string, <void *>&c_wisdoml_ptr)
2085        c_wisdoml[counterl] = 0
2086        try:
2087            py_wisdoml = c_wisdoml
2088        finally:
2089            free(c_wisdoml)
2090
2091    return (py_wisdom, py_wisdomf, py_wisdoml)
2092
2093def import_wisdom(wisdom):
2094    '''import_wisdom(wisdom)
2095
2096    Function that imports wisdom from the passed tuple
2097    of strings.
2098
2099    The first string in the tuple is the string for the double
2100    precision wisdom. The second string in the tuple is the string
2101    for the single precision wisdom. The third string in the tuple
2102    is the string for the long double precision wisdom.
2103
2104    The tuple that is returned from :func:`~pyfftw.export_wisdom`
2105    can be used as the argument to this function.
2106
2107    This function returns a tuple of boolean values indicating
2108    the success of loading each of the wisdom types (double, float
2109    and long double, in that order).
2110    '''
2111
2112    cdef:
2113        char* c_wisdom = wisdom[0]
2114        char* c_wisdomf = wisdom[1]
2115        char* c_wisdoml = wisdom[2]
2116
2117        bint success  = False
2118        bint successf = False
2119        bint successl = False
2120
2121    IF HAVE_DOUBLE:
2122        success = fftw_import_wisdom_from_string(c_wisdom)
2123    IF HAVE_SINGLE:
2124        successf = fftwf_import_wisdom_from_string(c_wisdomf)
2125    IF HAVE_LONG:
2126        successl = fftwl_import_wisdom_from_string(c_wisdoml)
2127    return (success, successf, successl)
2128
2129#def export_wisdom_to_files(
2130#        double_wisdom_file=None,
2131#        single_wisdom_file=None,
2132#        long_double_wisdom_file=None):
2133#    '''export_wisdom_to_file(double_wisdom_file=None, single_wisdom_file=None, long_double_wisdom_file=None)
2134#
2135#    Export the wisdom to the passed files.
2136#
2137#    The double precision wisdom is written to double_wisdom_file.
2138#    The single precision wisdom is written to single_wisdom_file.
2139#    The long double precision wisdom is written to
2140#    long_double_wisdom_file.
2141#
2142#    If any of the arguments are None, then nothing is done for that
2143#    file.
2144#
2145#    This function returns a tuple of boolean values indicating
2146#    the success of storing each of the wisdom types (double, float
2147#    and long double, in that order).
2148#    '''
2149#    cdef bint success = True
2150#    cdef bint successf = True
2151#    cdef bint successl = True
2152#
2153#    cdef char *_double_wisdom_file
2154#    cdef char *_single_wisdom_file
2155#    cdef char *_long_double_wisdom_file
2156#
2157#
2158#    if double_wisdom_file is not None:
2159#        _double_wisdom_file = double_wisdom_file
2160#        success = fftw_export_wisdom_to_filename(_double_wisdom_file)
2161#
2162#    if single_wisdom_file is not None:
2163#        _single_wisdom_file = single_wisdom_file
2164#        successf = fftwf_export_wisdom_to_filename(_single_wisdom_file)
2165#
2166#    if long_double_wisdom_file is not None:
2167#        _long_double_wisdom_file = long_double_wisdom_file
2168#        successl = fftwl_export_wisdom_to_filename(
2169#                _long_double_wisdom_file)
2170#
2171#    return (success, successf, successl)
2172#
2173#def import_wisdom_to_files(
2174#        double_wisdom_file=None,
2175#        single_wisdom_file=None,
2176#        long_double_wisdom_file=None):
2177#    '''import_wisdom_to_file(double_wisdom_file=None, single_wisdom_file=None, long_double_wisdom_file=None)
2178#
2179#    import the wisdom to the passed files.
2180#
2181#    The double precision wisdom is imported from double_wisdom_file.
2182#    The single precision wisdom is imported from single_wisdom_file.
2183#    The long double precision wisdom is imported from
2184#    long_double_wisdom_file.
2185#
2186#    If any of the arguments are None, then nothing is done for that
2187#    file.
2188#
2189#    This function returns a tuple of boolean values indicating
2190#    the success of loading each of the wisdom types (double, float
2191#    and long double, in that order).
2192#    '''
2193#    cdef bint success = True
2194#    cdef bint successf = True
2195#    cdef bint successl = True
2196#
2197#    cdef char *_double_wisdom_file
2198#    cdef char *_single_wisdom_file
2199#    cdef char *_long_double_wisdom_file
2200#
2201#    if double_wisdom_file is not None:
2202#        _double_wisdom_file = double_wisdom_file
2203#        success = fftw_import_wisdom_from_filename(_double_wisdom_file)
2204#
2205#    if single_wisdom_file is not None:
2206#        _single_wisdom_file = single_wisdom_file
2207#        successf = fftwf_import_wisdom_from_filename(_single_wisdom_file)
2208#
2209#    if long_double_wisdom_file is not None:
2210#        _long_double_wisdom_file = long_double_wisdom_file
2211#        successl = fftwl_import_wisdom_from_filename(
2212#                _long_double_wisdom_file)
2213#
2214#    return (success, successf, successl)
2215
2216def forget_wisdom():
2217    '''forget_wisdom()
2218
2219    Forget all the accumulated wisdom.
2220    '''
2221    IF HAVE_DOUBLE:
2222        fftw_forget_wisdom()
2223    IF HAVE_SINGLE:
2224        fftwf_forget_wisdom()
2225    IF HAVE_LONG:
2226        fftwl_forget_wisdom()
2227