GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
fft.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2022 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
38OCTAVE_NAMESPACE_BEGIN
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 // FIXME: This seems strange and unnecessary (10/21/16).
83 // How would you ever arrive at an octave_value object without correct dims?
84 // We certainly don't make this check every other place in Octave.
85 for (octave_idx_type i = 0; i < ndims; i++)
86 if (dims(i) < 0)
87 return retval;
88
89 if (dim < 0)
90 {
91 dim = dims.first_non_singleton ();
92
93 // And if the first argument is scalar?
94 if (dim == ndims)
95 dim = 1;
96 }
97
98 if (n_points < 0)
99 n_points = dims(dim);
100 else
101 dims(dim) = n_points;
102
103 if (n_points == 0 || dims.any_zero ())
104 {
105 if (arg.is_single_type ())
106 return octave_value (FloatNDArray (dims));
107 else
108 return octave_value (NDArray (dims));
109 }
110
111 if (n_points == 1)
112 {
113 octave_value_list idx (ndims);
114 for (octave_idx_type i = 0; i < ndims; i++)
115 idx(i) = idx_vector::colon;
116 idx(dim) = idx_vector (0);
117
118 return arg.index_op (idx);
119 }
120
121 if (arg.is_single_type ())
122 {
123 if (arg.isreal ())
124 {
125 FloatNDArray nda = arg.float_array_value ();
126
127 nda.resize (dims, 0.0);
128 retval = (type != 0 ? nda.ifourier (dim) : nda.fourier (dim));
129 }
130 else
131 {
133
134 cnda.resize (dims, 0.0);
135 retval = (type != 0 ? cnda.ifourier (dim) : cnda.fourier (dim));
136 }
137 }
138 else
139 {
140 if (arg.isreal ())
141 {
142 NDArray nda = arg.array_value ();
143
144 nda.resize (dims, 0.0);
145 retval = (type != 0 ? nda.ifourier (dim) : nda.fourier (dim));
146 }
147 else if (arg.iscomplex ())
148 {
150
151 cnda.resize (dims, 0.0);
152 retval = (type != 0 ? cnda.ifourier (dim) : cnda.fourier (dim));
153 }
154 else
155 err_wrong_type_arg (fcn, arg);
156 }
157
158 return retval;
159}
160
161/*
162%!testif HAVE_FFTW
163%! assert (fft ([]), [])
164%!testif HAVE_FFTW
165%! assert (fft (zeros (10,0)), zeros (10,0))
166%!testif HAVE_FFTW
167%! assert (fft (zeros (0,10)), zeros (0,10))
168%!testif HAVE_FFTW
169%! assert (fft (0), 0)
170%!testif HAVE_FFTW
171%! assert (fft (1), 1)
172%!testif HAVE_FFTW
173%! assert (fft (ones (2,2)), [2,2; 0,0])
174%!testif HAVE_FFTW
175%! assert (fft (eye (2,2)), [1,1; 1,-1])
176
177%!testif HAVE_FFTW
178%! assert (fft (single ([])), single ([]))
179%!testif HAVE_FFTW
180%! assert (fft (zeros (10,0,"single")), zeros (10,0,"single"))
181%!testif HAVE_FFTW
182%! assert (fft (zeros (0,10,"single")), zeros (0,10,"single"))
183%!testif HAVE_FFTW
184%! assert (fft (single (0)), single (0))
185%!testif HAVE_FFTW
186%! assert (fft (single (1)), single (1))
187%!testif HAVE_FFTW
188%! assert (fft (ones (2,2,"single")), single ([2,2; 0,0]))
189%!testif HAVE_FFTW
190%! assert (fft (eye (2,2,"single")), single ([1,1; 1,-1]))
191
192%!error fft ()
193*/
194
195
196DEFUN (fft, args, ,
197 doc: /* -*- texinfo -*-
198@deftypefn {} {} fft (@var{x})
199@deftypefnx {} {} fft (@var{x}, @var{n})
200@deftypefnx {} {} fft (@var{x}, @var{n}, @var{dim})
201Compute the discrete Fourier transform of @var{x} using
202a Fast Fourier Transform (FFT) algorithm.
203
204The FFT is calculated along the first non-singleton dimension of the
205array. Thus if @var{x} is a matrix, @code{fft (@var{x})} computes the
206FFT for each column of @var{x}.
207
208If called with two arguments, @var{n} is expected to be an integer
209specifying the number of elements of @var{x} to use, or an empty
210matrix to specify that its value should be ignored. If @var{n} is
211larger than the dimension along which the FFT is calculated, then
212@var{x} is resized and padded with zeros. Otherwise, if @var{n} is
213smaller than the dimension along which the FFT is calculated, then
214@var{x} is truncated.
215
216If called with three arguments, @var{dim} is an integer specifying the
217dimension of the matrix along which the FFT is performed.
218@seealso{ifft, fft2, fftn, fftw}
219@end deftypefn */)
220{
221 return do_fft (args, "fft", 0);
222}
223
224
225DEFUN (ifft, args, ,
226 doc: /* -*- texinfo -*-
227@deftypefn {} {} ifft (@var{x})
228@deftypefnx {} {} ifft (@var{x}, @var{n})
229@deftypefnx {} {} ifft (@var{x}, @var{n}, @var{dim})
230Compute the inverse discrete Fourier transform of @var{x}
231using a Fast Fourier Transform (FFT) algorithm.
232
233The inverse FFT is calculated along the first non-singleton dimension
234of the array. Thus if @var{x} is a matrix, @code{fft (@var{x})} computes
235the inverse FFT for each column of @var{x}.
236
237If called with two arguments, @var{n} is expected to be an integer
238specifying the number of elements of @var{x} to use, or an empty
239matrix to specify that its value should be ignored. If @var{n} is
240larger than the dimension along which the inverse FFT is calculated, then
241@var{x} is resized and padded with zeros. Otherwise, if @var{n} is
242smaller than the dimension along which the inverse FFT is calculated,
243then @var{x} is truncated.
244
245If called with three arguments, @var{dim} is an integer specifying the
246dimension of the matrix along which the inverse FFT is performed.
247@seealso{fft, ifft2, ifftn, fftw}
248@end deftypefn */)
249{
250 return do_fft (args, "ifft", 1);
251}
252
253/*
254## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
255## Comalco Research and Technology
256## 02 May 2000
257%!testif HAVE_FFTW
258%! N = 64;
259%! n = 4;
260%! t = 2*pi*(0:1:N-1)/N;
261%! s = cos (n*t);
262%! S = fft (s);
263%!
264%! answer = zeros (size (t));
265%! answer(n+1) = N/2;
266%! answer(N-n+1) = N/2;
267%!
268%! assert (S, answer, 4*N*eps);
269
270## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
271## Comalco Research and Technology
272## 02 May 2000
273%!testif HAVE_FFTW
274%! N = 64;
275%! n = 7;
276%! t = 2*pi*(0:1:N-1)/N;
277%! s = cos (n*t);
278%!
279%! S = zeros (size (t));
280%! S(n+1) = N/2;
281%! S(N-n+1) = N/2;
282%!
283%! assert (ifft (S), s, 4*N*eps);
284
285## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
286## Comalco Research and Technology
287## 02 May 2000
288%!testif HAVE_FFTW
289%! N = 64;
290%! n = 4;
291%! t = single (2*pi*(0:1:N-1)/N);
292%! s = cos (n*t);
293%! S = fft (s);
294%!
295%! answer = zeros (size (t), "single");
296%! answer(n+1) = N/2;
297%! answer(N-n+1) = N/2;
298%!
299%! assert (S, answer, 4*N*eps ("single"));
300
301## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
302## Comalco Research and Technology
303## 02 May 2000
304%!testif HAVE_FFTW
305%! N = 64;
306%! n = 7;
307%! t = 2*pi*(0:1:N-1)/N;
308%! s = cos (n*t);
309%!
310%! S = zeros (size (t), "single");
311%! S(n+1) = N/2;
312%! S(N-n+1) = N/2;
313%!
314%! assert (ifft (S), s, 4*N*eps ("single"));
315*/
316
317OCTAVE_NAMESPACE_END
OCTARRAY_API void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array.cc:1010
OCTAVE_API ComplexNDArray fourier(int dim=1) const
Definition: CNDArray.cc:58
OCTAVE_API ComplexNDArray ifourier(int dim=1) const
Definition: CNDArray.cc:89
OCTAVE_API FloatComplexNDArray ifourier(int dim=1) const
Definition: fCNDArray.cc:89
OCTAVE_API FloatComplexNDArray fourier(int dim=1) const
Definition: fCNDArray.cc:58
OCTAVE_API FloatComplexNDArray ifourier(int dim=1) const
Definition: fNDArray.cc:89
OCTAVE_API FloatComplexNDArray fourier(int dim=1) const
Definition: fNDArray.cc:58
OCTAVE_API ComplexNDArray ifourier(int dim=1) const
Definition: dNDArray.cc:131
OCTAVE_API ComplexNDArray fourier(int dim=1) const
Definition: dNDArray.cc:100
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
int first_non_singleton(int def=0) const
Definition: dim-vector.h:444
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:257
bool any_zero(void) const
Definition: dim-vector.h:316
static const idx_vector colon
Definition: idx-vector.h:483
octave_idx_type length(void) const
Definition: ovl.h:113
bool isreal(void) const
Definition: ov.h:783
octave_value index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov.h:550
ComplexNDArray complex_array_value(bool frc_str_conv=false) const
Definition: ov.h:923
NDArray array_value(bool frc_str_conv=false) const
Definition: ov.h:904
bool is_single_type(void) const
Definition: ov.h:743
FloatComplexNDArray float_complex_array_value(bool frc_str_conv=false) const
Definition: ov.h:927
FloatNDArray float_array_value(bool frc_str_conv=false) const
Definition: ov.h:907
bool iscomplex(void) const
Definition: ov.h:786
dim_vector dims(void) const
Definition: ov.h:586
OCTINTERP_API void print_usage(void)
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:980
void err_wrong_type_arg(const char *name, const char *s)
Definition: errwarn.cc:166
static OCTAVE_NAMESPACE_BEGIN octave_value do_fft(const octave_value_list &args, const char *fcn, int type)
Definition: fft.cc:41
octave::idx_vector idx_vector
Definition: idx-vector.h:1037
int nint(double x)
Definition: lo-mappers.cc:212
bool isnan(bool)
Definition: lo-mappers.h:178
octave_idx_type nint_big(double x)
Definition: lo-mappers.cc:184
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))