GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
fft.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2025 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include "lo-mappers.h"
31
32#include "defun.h"
33#include "error.h"
34#include "errwarn.h"
35#include "ovl.h"
36#include "utils.h"
37
39
40static octave_value
41do_fft (const octave_value_list& args, const char *fcn, int type)
42{
43 int nargin = args.length ();
44
45 if (nargin < 1 || nargin > 3)
46 print_usage ();
47
48 octave_value retval;
49 octave_value arg = args(0);
50 octave_idx_type n_points = -1;
51 dim_vector dims = arg.dims ();
52 int ndims = dims.ndims ();
53 int dim = -1;
54
55 if (nargin > 1)
56 {
57 if (! args(1).isempty ())
58 {
59 double dval = args(1).double_value ();
60 if (math::isnan (dval))
61 error ("%s: number of points (N) cannot be NaN", fcn);
62
63 n_points = math::nint_big (dval);
64 if (n_points < 0)
65 error ("%s: number of points (N) must be greater than zero", fcn);
66 }
67 }
68
69 if (nargin > 2)
70 {
71 double dval = args(2).double_value ();
72 if (math::isnan (dval))
73 error ("%s: DIM cannot be NaN", fcn);
74 else if (dval < 1 || dval > ndims)
75 error ("%s: DIM must be a valid dimension along which to perform FFT",
76 fcn);
77 else
78 // to be safe, cast it back to int since dim is an int
79 dim = math::nint (dval) - 1;
80 }
81
82 if (dim < 0)
83 {
84 dim = dims.first_non_singleton ();
85
86 // And if the first argument is scalar?
87 if (dim == ndims)
88 dim = 1;
89 }
90
91 if (n_points < 0)
92 n_points = dims(dim);
93 else
94 dims(dim) = n_points;
95
96 if (n_points == 0 || dims.any_zero ())
97 {
98 if (arg.is_single_type ())
99 return octave_value (FloatNDArray (dims));
100 else
101 return octave_value (NDArray (dims));
102 }
103
104 if (n_points == 1)
105 {
106 octave_value_list idx (ndims);
107 for (octave_idx_type i = 0; i < ndims; i++)
108 idx(i) = idx_vector::colon;
109 idx(dim) = idx_vector (0);
110
111 return arg.index_op (idx);
112 }
113
114 if (arg.is_single_type ())
115 {
116 if (arg.isreal ())
117 {
118 FloatNDArray nda = arg.float_array_value ();
119
120 nda.resize (dims, 0.0);
121 retval = (type != 0 ? nda.ifourier (dim) : nda.fourier (dim));
122 }
123 else
124 {
126
127 cnda.resize (dims, 0.0);
128 retval = (type != 0 ? cnda.ifourier (dim) : cnda.fourier (dim));
129 }
130 }
131 else
132 {
133 if (arg.isreal ())
134 {
135 NDArray nda = arg.array_value ();
136
137 nda.resize (dims, 0.0);
138 retval = (type != 0 ? nda.ifourier (dim) : nda.fourier (dim));
139 }
140 else if (arg.iscomplex ())
141 {
143
144 cnda.resize (dims, 0.0);
145 retval = (type != 0 ? cnda.ifourier (dim) : cnda.fourier (dim));
146 }
147 else
148 err_wrong_type_arg (fcn, arg);
149 }
150
151 return retval;
152}
153
154/*
155%!testif HAVE_FFTW
156%! assert (fft ([]), [])
157%!testif HAVE_FFTW
158%! assert (fft (zeros (10,0)), zeros (10,0))
159%!testif HAVE_FFTW
160%! assert (fft (zeros (0,10)), zeros (0,10))
161%!testif HAVE_FFTW
162%! assert (fft (0), 0)
163%!testif HAVE_FFTW
164%! assert (fft (1), 1)
165%!testif HAVE_FFTW
166%! assert (fft (ones (2,2)), [2,2; 0,0])
167%!testif HAVE_FFTW
168%! assert (fft (eye (2,2)), [1,1; 1,-1])
169
170%!testif HAVE_FFTW
171%! assert (fft (single ([])), single ([]))
172%!testif HAVE_FFTW
173%! assert (fft (zeros (10,0,"single")), zeros (10,0,"single"))
174%!testif HAVE_FFTW
175%! assert (fft (zeros (0,10,"single")), zeros (0,10,"single"))
176%!testif HAVE_FFTW
177%! assert (fft (single (0)), single (0))
178%!testif HAVE_FFTW
179%! assert (fft (single (1)), single (1))
180%!testif HAVE_FFTW
181%! assert (fft (ones (2,2,"single")), single ([2,2; 0,0]))
182%!testif HAVE_FFTW
183%! assert (fft (eye (2,2,"single")), single ([1,1; 1,-1]))
184
185%!error fft ()
186*/
187
188
189DEFUN (fft, args, ,
190 doc: /* -*- texinfo -*-
191@deftypefn {} {@var{y} =} fft (@var{x})
192@deftypefnx {} {@var{y} =} fft (@var{x}, @var{n})
193@deftypefnx {} {@var{y} =} fft (@var{x}, @var{n}, @var{dim})
194Compute the discrete Fourier transform of @var{x} using
195a Fast Fourier Transform (FFT) algorithm.
196
197The FFT is calculated along the first non-singleton dimension of the
198array. Thus if @var{x} is a matrix, @code{fft (@var{x})} computes the
199FFT for each column of @var{x}.
200
201If called with two arguments, @var{n} is expected to be an integer
202specifying the number of elements of @var{x} to use, or an empty
203matrix to specify that its value should be ignored. If @var{n} is
204larger than the dimension along which the FFT is calculated, then
205@var{x} is resized and padded with zeros. Otherwise, if @var{n} is
206smaller than the dimension along which the FFT is calculated, then
207@var{x} is truncated.
208
209If called with three arguments, @var{dim} is an integer specifying the
210dimension of the matrix along which the FFT is performed.
211@seealso{ifft, fft2, fftn, fftw}
212@end deftypefn */)
213{
214 return do_fft (args, "fft", 0);
215}
216
217
218DEFUN (ifft, args, ,
219 doc: /* -*- texinfo -*-
220@deftypefn {} {@var{x} =} ifft (@var{y})
221@deftypefnx {} {@var{x} =} ifft (@var{y}, @var{n})
222@deftypefnx {} {@var{x} =} ifft (@var{y}, @var{n}, @var{dim})
223Compute the inverse discrete Fourier transform of @var{y}
224using a Fast Fourier Transform (FFT) algorithm.
225
226The inverse FFT is calculated along the first non-singleton dimension
227of the array. Thus if @var{y} is a matrix, @code{ifft (@var{y})} computes
228the inverse FFT for each column of @var{y}.
229
230If called with two arguments, @var{n} is expected to be an integer
231specifying the number of elements of @var{y} to use, or an empty
232matrix to specify that its value should be ignored. If @var{n} is
233larger than the dimension along which the inverse FFT is calculated, then
234@var{y} is resized and padded with zeros. Otherwise, if @var{n} is
235smaller than the dimension along which the inverse FFT is calculated,
236then @var{y} is truncated.
237
238If called with three arguments, @var{dim} is an integer specifying the
239dimension of the matrix along which the inverse FFT is performed.
240@seealso{fft, ifft2, ifftn, fftw}
241@end deftypefn */)
242{
243 return do_fft (args, "ifft", 1);
244}
245
246/*
247## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
248## Comalco Research and Technology
249## 02 May 2000
250%!testif HAVE_FFTW
251%! N = 64;
252%! n = 4;
253%! t = 2*pi*(0:1:N-1)/N;
254%! s = cos (n*t);
255%! S = fft (s);
256%!
257%! answer = zeros (size (t));
258%! answer(n+1) = N/2;
259%! answer(N-n+1) = N/2;
260%!
261%! assert (S, answer, 4*N*eps);
262
263## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
264## Comalco Research and Technology
265## 02 May 2000
266%!testif HAVE_FFTW
267%! N = 64;
268%! n = 7;
269%! t = 2*pi*(0:1:N-1)/N;
270%! s = cos (n*t);
271%!
272%! S = zeros (size (t));
273%! S(n+1) = N/2;
274%! S(N-n+1) = N/2;
275%!
276%! assert (ifft (S), s, 4*N*eps);
277
278## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
279## Comalco Research and Technology
280## 02 May 2000
281%!testif HAVE_FFTW
282%! N = 64;
283%! n = 4;
284%! t = single (2*pi*(0:1:N-1)/N);
285%! s = cos (n*t);
286%! S = fft (s);
287%!
288%! answer = zeros (size (t), "single");
289%! answer(n+1) = N/2;
290%! answer(N-n+1) = N/2;
291%!
292%! assert (S, answer, 4*N* eps ("single"));
293
294## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
295## Comalco Research and Technology
296## 02 May 2000
297%!testif HAVE_FFTW
298%! N = 64;
299%! n = 7;
300%! t = 2*pi*(0:1:N-1)/N;
301%! s = cos (n*t);
302%!
303%! S = zeros (size (t), "single");
304%! S(n+1) = N/2;
305%! S(N-n+1) = N/2;
306%!
307%! assert (ifft (S), s, 4*N* eps ("single"));
308
309%!testif HAVE_FFTW <*64729>
310%! x = rand (5, 5, 5, 5);
311%! old_planner = fftw ('planner', 'measure');
312%! unwind_protect
313%! y = fft (x);
314%! y = fft (x); # second invocation might crash Octave
315%! assert (size (y), [5, 5, 5, 5]);
316%! unwind_protect_cleanup
317%! fftw ('planner', old_planner);
318%! end_unwind_protect
319
320%!testif HAVE_FFTW <*64729>
321%! x = rand (5, 5, 5, 5, 'single');
322%! old_planner = fftw ('planner', 'measure');
323%! unwind_protect
324%! y = fft (x);
325%! y = fft (x); # second invocation might crash Octave
326%! assert (size (y), [5, 5, 5, 5]);
327%! unwind_protect_cleanup
328%! fftw ('planner', old_planner);
329%! end_unwind_protect
330
331%!testif HAVE_FFTW <*64733>
332%! old_planner = fftw ('planner', 'measure');
333%! unwind_protect
334%! assert (ifft ([2, 4, 6, 8]), [5, -1-1i, -1, -1+1i]);
335%! unwind_protect_cleanup
336%! fftw ('planner', old_planner);
337%! end_unwind_protect
338
339%!testif HAVE_FFTW <*64733>
340%! old_planner = fftw ('planner', 'measure');
341%! unwind_protect
342%! assert (ifft (single ([2, 4, 6, 8])), single ([5, -1-1i, -1, -1+1i]));
343%! unwind_protect_cleanup
344%! fftw ('planner', old_planner);
345%! end_unwind_protect
346*/
347
348OCTAVE_END_NAMESPACE(octave)
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
ComplexNDArray fourier(int dim=1) const
Definition CNDArray.cc:58
ComplexNDArray ifourier(int dim=1) const
Definition CNDArray.cc:89
FloatComplexNDArray ifourier(int dim=1) const
Definition fCNDArray.cc:89
FloatComplexNDArray fourier(int dim=1) const
Definition fCNDArray.cc:58
FloatComplexNDArray ifourier(int dim=1) const
Definition fNDArray.cc:89
FloatComplexNDArray fourier(int dim=1) const
Definition fNDArray.cc:58
ComplexNDArray ifourier(int dim=1) const
Definition dNDArray.cc:131
ComplexNDArray fourier(int dim=1) const
Definition dNDArray.cc:100
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:90
octave_idx_type ndims() const
Number of dimensions.
Definition dim-vector.h:253
bool any_zero() const
Definition dim-vector.h:312
int first_non_singleton(int def=0) const
Definition dim-vector.h:440
static const idx_vector colon
Definition idx-vector.h:464
octave_idx_type length() const
Definition ovl.h:111
octave_value index_op(const octave_value_list &idx, bool resize_ok=false)
Definition ov.h:504
bool isreal() const
Definition ov.h:738
ComplexNDArray complex_array_value(bool frc_str_conv=false) const
Definition ov.h:884
bool is_single_type() const
Definition ov.h:698
bool iscomplex() const
Definition ov.h:741
NDArray array_value(bool frc_str_conv=false) const
Definition ov.h:865
FloatComplexNDArray float_complex_array_value(bool frc_str_conv=false) const
Definition ov.h:888
FloatNDArray float_array_value(bool frc_str_conv=false) const
Definition ov.h:868
dim_vector dims() const
Definition ov.h:541
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage()
Definition defun-int.h:72
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition defun.h:56
void error(const char *fmt,...)
Definition error.cc:1003
void err_wrong_type_arg(const char *name, const char *s)
Definition errwarn.cc:166