fft.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1997-2012 David Bateman
00004 Copyright (C) 1996-1997 John W. Eaton
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
00021 
00022 */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #include "lo-mappers.h"
00029 
00030 #include "defun-dld.h"
00031 #include "error.h"
00032 #include "gripes.h"
00033 #include "oct-obj.h"
00034 #include "utils.h"
00035 
00036 #if defined (HAVE_FFTW)
00037 #define FFTSRC "@sc{fftw}"
00038 #else
00039 #define FFTSRC "@sc{fftpack}"
00040 #endif
00041 
00042 static octave_value
00043 do_fft (const octave_value_list &args, const char *fcn, int type)
00044 {
00045   octave_value retval;
00046 
00047   int nargin = args.length ();
00048 
00049   if (nargin < 1 || nargin > 3)
00050     {
00051       print_usage ();
00052       return retval;
00053     }
00054 
00055   octave_value arg = args(0);
00056   dim_vector dims = arg.dims ();
00057   octave_idx_type n_points = -1;
00058   int dim = -1;
00059 
00060   if (nargin > 1)
00061     {
00062       if (! args(1).is_empty ())
00063         {
00064           double dval = args(1).double_value ();
00065           if (xisnan (dval))
00066             error ("%s: number of points (N) cannot be NaN", fcn);
00067           else
00068             {
00069               n_points = NINTbig (dval);
00070               if (n_points < 0)
00071                 error ("%s: number of points (N) must be greater than zero", fcn);
00072             }
00073         }
00074     }
00075 
00076   if (error_state)
00077     return retval;
00078 
00079   if (nargin > 2)
00080     {
00081       double dval = args(2).double_value ();
00082       if (xisnan (dval))
00083         error ("%s: DIM cannot be NaN", fcn);
00084       else if (dval < 1 || dval > dims.length ())
00085         error ("%s: DIM must be a valid dimension along which to perform FFT", fcn);
00086       else
00087         // to be safe, cast it back to int since dim is an int
00088         dim = NINT (dval) - 1;
00089     }
00090 
00091   if (error_state)
00092     return retval;
00093 
00094   for (octave_idx_type i = 0; i < dims.length (); i++)
00095     if (dims(i) < 0)
00096       return retval;
00097 
00098   if (dim < 0)
00099     {
00100       for (octave_idx_type i = 0; i < dims.length (); i++)
00101         if (dims(i) > 1)
00102           {
00103             dim = i;
00104             break;
00105           }
00106 
00107       // And if the first argument is scalar?
00108       if (dim < 0)
00109         dim = 1;
00110     }
00111 
00112   if (n_points < 0)
00113     n_points = dims (dim);
00114   else
00115     dims (dim) = n_points;
00116 
00117   if (dims.any_zero () || n_points == 0)
00118     {
00119       if (arg.is_single_type ())
00120         return octave_value (FloatNDArray (dims));
00121       else
00122         return octave_value (NDArray (dims));
00123     }
00124 
00125   if (arg.is_single_type ())
00126     {
00127       if (arg.is_real_type ())
00128         {
00129           FloatNDArray nda = arg.float_array_value ();
00130 
00131           if (! error_state)
00132             {
00133               nda.resize (dims, 0.0);
00134               retval = (type != 0 ? nda.ifourier (dim) : nda.fourier (dim));
00135             }
00136         }
00137       else
00138         {
00139           FloatComplexNDArray cnda = arg.float_complex_array_value ();
00140 
00141           if (! error_state)
00142             {
00143               cnda.resize (dims, 0.0);
00144               retval = (type != 0 ? cnda.ifourier (dim) : cnda.fourier (dim));
00145             }
00146         }
00147     }
00148   else
00149     {
00150       if (arg.is_real_type ())
00151         {
00152           NDArray nda = arg.array_value ();
00153 
00154           if (! error_state)
00155             {
00156               nda.resize (dims, 0.0);
00157               retval = (type != 0 ? nda.ifourier (dim) : nda.fourier (dim));
00158             }
00159         }
00160       else if (arg.is_complex_type ())
00161         {
00162           ComplexNDArray cnda = arg.complex_array_value ();
00163 
00164           if (! error_state)
00165             {
00166               cnda.resize (dims, 0.0);
00167               retval = (type != 0 ? cnda.ifourier (dim) : cnda.fourier (dim));
00168             }
00169         }
00170       else
00171         {
00172           gripe_wrong_type_arg (fcn, arg);
00173         }
00174     }
00175 
00176   return retval;
00177 }
00178 
00179 /*
00180 
00181 %!error(fft())
00182 %!assert(fft([]), [])
00183 %!assert(fft(zeros(10,0)), zeros(10,0))
00184 %!assert(fft(zeros(0,10)), zeros(0,10))
00185 %!assert(fft(0), 0)
00186 %!assert(fft(1), 1)
00187 %!assert(fft(ones(2,2)), [2,2; 0,0])
00188 %!assert(fft(eye(2,2)), [1,1; 1,-1])
00189 
00190 %!assert(fft(single([])), single([]))
00191 %!assert(fft(zeros(10,0,'single')), zeros(10,0,'single'))
00192 %!assert(fft(zeros(0,10,'single')), zeros(0,10,'single'))
00193 %!assert(fft(single(0)), single(0))
00194 %!assert(fft(single(1)), single(1))
00195 %!assert(fft(ones(2,2,'single')), single([2,2; 0,0]))
00196 %!assert(fft(eye(2,2,'single')), single([1,1; 1,-1]))
00197 
00198 */
00199 
00200 
00201 DEFUN_DLD (fft, args, ,
00202   "-*- texinfo -*-\n\
00203 @deftypefn  {Loadable Function} {} fft (@var{x})\n\
00204 @deftypefnx {Loadable Function} {} fft (@var{x}, @var{n})\n\
00205 @deftypefnx {Loadable Function} {} fft (@var{x}, @var{n}, @var{dim})\n\
00206 Compute the discrete Fourier transform of @var{A} using\n\
00207 a Fast Fourier Transform (FFT) algorithm.\n\
00208 \n\
00209 The FFT is calculated along the first non-singleton dimension of the\n\
00210 array.  Thus if @var{x} is a matrix, @code{fft (@var{x})} computes the\n\
00211 FFT for each column of @var{x}.\n\
00212 \n\
00213 If called with two arguments, @var{n} is expected to be an integer\n\
00214 specifying the number of elements of @var{x} to use, or an empty\n\
00215 matrix to specify that its value should be ignored.  If @var{n} is\n\
00216 larger than the dimension along which the FFT is calculated, then\n\
00217 @var{x} is resized and padded with zeros.  Otherwise, if @var{n} is\n\
00218 smaller than the dimension along which the FFT is calculated, then\n\
00219 @var{x} is truncated.\n\
00220 \n\
00221 If called with three arguments, @var{dim} is an integer specifying the\n\
00222 dimension of the matrix along which the FFT is performed\n\
00223 @seealso{ifft, fft2, fftn, fftw}\n\
00224 @end deftypefn")
00225 {
00226   return do_fft (args, "fft", 0);
00227 }
00228 
00229 
00230 DEFUN_DLD (ifft, args, ,
00231   "-*- texinfo -*-\n\
00232 @deftypefn  {Loadable Function} {} ifft (@var{x})\n\
00233 @deftypefnx {Loadable Function} {} ifft (@var{x}, @var{n})\n\
00234 @deftypefnx {Loadable Function} {} ifft (@var{x}, @var{n}, @var{dim})\n\
00235 Compute the inverse discrete Fourier transform of @var{A}\n\
00236 using a Fast Fourier Transform (FFT) algorithm.\n\
00237 \n\
00238 The inverse FFT is calculated along the first non-singleton dimension\n\
00239 of the array.  Thus if @var{x} is a matrix, @code{fft (@var{x})} computes\n\
00240 the inverse FFT for each column of @var{x}.\n\
00241 \n\
00242 If called with two arguments, @var{n} is expected to be an integer\n\
00243 specifying the number of elements of @var{x} to use, or an empty\n\
00244 matrix to specify that its value should be ignored.  If @var{n} is\n\
00245 larger than the dimension along which the inverse FFT is calculated, then\n\
00246 @var{x} is resized and padded with zeros.  Otherwise, if @var{n} is\n\
00247 smaller than the dimension along which the inverse FFT is calculated,\n\
00248 then @var{x} is truncated.\n\
00249 \n\
00250 If called with three arguments, @var{dim} is an integer specifying the\n\
00251 dimension of the matrix along which the inverse FFT is performed\n\
00252 @seealso{fft, ifft2, ifftn, fftw}\n\
00253 @end deftypefn")
00254 {
00255   return do_fft (args, "ifft", 1);
00256 }
00257 
00258 /*
00259 
00260 %% Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
00261 %%         Comalco Research and Technology
00262 %%         02 May 2000
00263 %!test
00264 %! N=64;
00265 %! n=4;
00266 %! t = 2*pi*(0:1:N-1)/N;
00267 %! s = cos(n*t);
00268 %! S = fft(s);
00269 %!
00270 %! answer = zeros (size(t));
00271 %! answer(n+1) = N/2;
00272 %! answer(N-n+1) = N/2;
00273 %!
00274 %! assert(S, answer, 4*N*eps);
00275 
00276 %% Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
00277 %%         Comalco Research and Technology
00278 %%         02 May 2000
00279 %!test
00280 %! N=64;
00281 %! n=7;
00282 %! t = 2*pi*(0:1:N-1)/N;
00283 %! s = cos(n*t);
00284 %!
00285 %! S = zeros (size(t));
00286 %! S(n+1) = N/2;
00287 %! S(N-n+1) = N/2;
00288 %!
00289 %! assert(ifft(S), s, 4*N*eps);
00290 
00291 %% Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
00292 %%         Comalco Research and Technology
00293 %%         02 May 2000
00294 %!test
00295 %! N=64;
00296 %! n=4;
00297 %! t = single (2*pi*(0:1:N-1)/N);
00298 %! s = cos(n*t);
00299 %! S = fft(s);
00300 %!
00301 %! answer = zeros (size(t),'single');
00302 %! answer(n+1) = N/2;
00303 %! answer(N-n+1) = N/2;
00304 %!
00305 %! assert(S, answer, 4*N*eps('single'));
00306 
00307 %% Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
00308 %%         Comalco Research and Technology
00309 %%         02 May 2000
00310 %!test
00311 %! N=64;
00312 %! n=7;
00313 %! t = 2*pi*(0:1:N-1)/N;
00314 %! s = cos(n*t);
00315 %!
00316 %! S = zeros (size(t),'single');
00317 %! S(n+1) = N/2;
00318 %! S(N-n+1) = N/2;
00319 %!
00320 %! assert(ifft(S), s, 4*N*eps('single'));
00321 
00322 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines