GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
fftw.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2006-2017 David Bateman
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <algorithm>
28 
29 #if defined (HAVE_FFTW3_H)
30 # include <fftw3.h>
31 #endif
32 
33 #include "oct-fftw.h"
34 
35 #include "defun-dld.h"
36 #include "error.h"
37 #include "ov.h"
38 
39 #include "errwarn.h"
40 
41 DEFUN_DLD (fftw, args, ,
42  doc: /* -*- texinfo -*-
43 @deftypefn {} {@var{method} =} fftw ("planner")
44 @deftypefnx {} {} fftw ("planner", @var{method})
45 @deftypefnx {} {@var{wisdom} =} fftw ("dwisdom")
46 @deftypefnx {} {} fftw ("dwisdom", @var{wisdom})
47 @deftypefnx {} {} fftw ("threads", @var{nthreads})
48 @deftypefnx {} {@var{nthreads} =} fftw ("threads")
49 
50 Manage @sc{fftw} wisdom data.
51 
52 Wisdom data can be used to significantly accelerate the calculation of the
53 FFTs, but implies an initial cost in its calculation. When the @sc{fftw}
54 libraries are initialized, they read a system wide wisdom file (typically in
55 @file{/etc/fftw/wisdom}), allowing wisdom to be shared between applications
56 other than Octave. Alternatively, the @code{fftw} function can be used to
57 import wisdom. For example,
58 
59 @example
60 @var{wisdom} = fftw ("dwisdom")
61 @end example
62 
63 @noindent
64 will save the existing wisdom used by Octave to the string @var{wisdom}.
65 This string can then be saved to a file and restored using the @code{save}
66 and @code{load} commands respectively. This existing wisdom can be
67 re-imported as follows
68 
69 @example
70 fftw ("dwisdom", @var{wisdom})
71 @end example
72 
73 If @var{wisdom} is an empty string, then the wisdom used is cleared.
74 
75 During the calculation of Fourier transforms further wisdom is generated.
76 The fashion in which this wisdom is generated is also controlled by
77 the @code{fftw} function. There are five different manners in which the
78 wisdom can be treated:
79 
80 @table @asis
81 @item @qcode{"estimate"}
82 Specifies that no run-time measurement of the optimal means of
83 calculating a particular is performed, and a simple heuristic is used
84 to pick a (probably sub-optimal) plan. The advantage of this method is
85 that there is little or no overhead in the generation of the plan, which
86 is appropriate for a Fourier transform that will be calculated once.
87 
88 @item @qcode{"measure"}
89 In this case a range of algorithms to perform the transform is considered
90 and the best is selected based on their execution time.
91 
92 @item @qcode{"patient"}
93 Similar to @qcode{"measure"}, but a wider range of algorithms is
94 considered.
95 
96 @item @qcode{"exhaustive"}
97 Like @qcode{"measure"}, but all possible algorithms that may be used to
98 treat the transform are considered.
99 
100 @item @qcode{"hybrid"}
101 As run-time measurement of the algorithm can be expensive, this is a
102 compromise where @qcode{"measure"} is used for transforms up to the size
103 of 8192 and beyond that the @qcode{"estimate"} method is used.
104 @end table
105 
106 The default method is @qcode{"estimate"}. The current method can
107 be queried with
108 
109 @example
110 @var{method} = fftw ("planner")
111 @end example
112 
113 @noindent
114 or set by using
115 
116 @example
117 fftw ("planner", @var{method})
118 @end example
119 
120 Note that calculated wisdom will be lost when restarting Octave. However,
121 the wisdom data can be reloaded if it is saved to a file as described
122 above. Saved wisdom files should not be used on different platforms since
123 they will not be efficient and the point of calculating the wisdom is lost.
124 
125 The number of threads used for computing the plans and executing the
126 transforms can be set with
127 
128 @example
129 fftw ("threads", @var{NTHREADS})
130 @end example
131 
132 Note that octave must be compiled with multi-threaded @sc{fftw} support for
133 this feature. The number of processors available to the current process is
134 used per default.
135 
136 @seealso{fft, ifft, fft2, ifft2, fftn, ifftn}
137 @end deftypefn */)
138 {
139 #if defined (HAVE_FFTW)
140 
141  int nargin = args.length ();
142 
143  if (nargin < 1 || nargin > 2)
144  print_usage ();
145 
147 
148  std::string arg0 = args(0).xstring_value ("fftw: first argument must be a string");
149 
150  if (arg0 == "planner")
151  {
152  if (nargin == 2) // planner setter
153  {
154  // Use STL function to convert to lower case
155  std::transform (arg0.begin (), arg0.end (), arg0.begin (), tolower);
156 
157  std::string arg1 = args(1).xstring_value ("fftw: METHOD must be a string");
158 
159  std::transform (arg1.begin (), arg1.end (), arg1.begin (), tolower);
164 
165  if (arg1 == "estimate")
166  {
169  }
170  else if (arg1 == "measure")
171  {
174  }
175  else if (arg1 == "patient")
176  {
179  }
180  else if (arg1 == "exhaustive")
181  {
184  }
185  else if (arg1 == "hybrid")
186  {
189  }
190  else
191  error ("fftw: unrecognized planner METHOD");
192 
193  meth = octave_fftw_planner::method (meth);
195 
196  if (meth == octave_fftw_planner::MEASURE)
197  retval = octave_value ("measure");
198  else if (meth == octave_fftw_planner::PATIENT)
199  retval = octave_value ("patient");
200  else if (meth == octave_fftw_planner::EXHAUSTIVE)
201  retval = octave_value ("exhaustive");
202  else if (meth == octave_fftw_planner::HYBRID)
203  retval = octave_value ("hybrid");
204  else
205  retval = octave_value ("estimate");
206  }
207  else //planner getter
208  {
211 
212  if (meth == octave_fftw_planner::MEASURE)
213  retval = octave_value ("measure");
214  else if (meth == octave_fftw_planner::PATIENT)
215  retval = octave_value ("patient");
216  else if (meth == octave_fftw_planner::EXHAUSTIVE)
217  retval = octave_value ("exhaustive");
218  else if (meth == octave_fftw_planner::HYBRID)
219  retval = octave_value ("hybrid");
220  else
221  retval = octave_value ("estimate");
222  }
223  }
224  else if (arg0 == "dwisdom")
225  {
226  if (nargin == 2) //dwisdom setter
227  {
228  // Use STL function to convert to lower case
229  std::transform (arg0.begin (), arg0.end (), arg0.begin (),
230  tolower);
231 
232  std::string arg1 = args(1).xstring_value ("fftw: WISDOM must be a string");
233 
234  char *str = fftw_export_wisdom_to_string ();
235  std::string wisdom_str (str);
236  free (str);
237 
238  if (arg1.length () < 1)
239  fftw_forget_wisdom ();
240  else if (! fftw_import_wisdom_from_string (arg1.c_str ()))
241  error ("fftw: could not import supplied WISDOM");
242 
243  retval = octave_value (wisdom_str);
244  }
245  else //dwisdom getter
246  {
247  char *str = fftw_export_wisdom_to_string ();
248  std::string wisdom_str (str);
249  free (str);
250  retval = octave_value (wisdom_str);
251  }
252  }
253  else if (arg0 == "swisdom")
254  {
255  //swisdom uses fftwf_ functions (float), dwisdom fftw_ (real)
256  if (nargin == 2) //swisdom setter
257  {
258  // Use STL function to convert to lower case
259  std::transform (arg0.begin (), arg0.end (), arg0.begin (),
260  tolower);
261 
262  std::string arg1 = args(1).xstring_value ("fftw: WISDOM must be a string");
263 
264  char *str = fftwf_export_wisdom_to_string ();
265  std::string wisdom_str (str);
266  free (str);
267 
268  if (arg1.length () < 1)
269  fftwf_forget_wisdom ();
270  else if (! fftwf_import_wisdom_from_string (arg1.c_str ()))
271  error ("fftw: could not import supplied WISDOM");
272 
273  retval = octave_value (wisdom_str);
274  }
275  else //swisdom getter
276  {
277  char *str = fftwf_export_wisdom_to_string ();
278  std::string wisdom_str (str);
279  free (str);
280  retval = octave_value (wisdom_str);
281  }
282  }
283  else if (arg0 == "threads")
284  {
285  if (nargin == 2) //threads setter
286  {
287  if (! args(1).is_real_scalar ())
288  error ("fftw: setting threads needs one integer argument");
289 
290  int nthreads = args(1).int_value();
291  if (nthreads < 1)
292  error ("fftw: number of threads must be >=1");
293 
294 #if defined (HAVE_FFTW3_THREADS)
295  octave_fftw_planner::threads (nthreads);
296 #else
297  err_disabled_feature ("fftw", "multithreaded FFTW");
298 #endif
299 #if defined (HAVE_FFTW3F_THREADS)
301 #else
302  err_disabled_feature ("fftw", "multithreaded FFTW");
303 #endif
304  }
305  else //threads getter
306 #if defined (HAVE_FFTW3_THREADS)
308 #else
309  retval = 1;
310 #endif
311  }
312  else
313  error ("fftw: unrecognized argument");
314 
315  return retval;
316 
317 #else
318 
319  octave_unused_parameter (args);
320 
321  err_disabled_feature ("fftw", "the FFTW3 planner");
322 
323 #endif
324 }
325 
326 /*
327 %!testif HAVE_FFTW
328 %! def_method = fftw ("planner");
329 %! unwind_protect
330 %! method = "estimate";
331 %! fftw ("planner", method);
332 %! assert (fftw ("planner"), method);
333 %! method = "measure";
334 %! fftw ("planner", method);
335 %! assert (fftw ("planner"), method);
336 %! method = "patient";
337 %! fftw ("planner", method);
338 %! assert (fftw ("planner"), method);
339 %! method = "exhaustive";
340 %! fftw ("planner", method);
341 %! assert (fftw ("planner"), method);
342 %! method = "hybrid";
343 %! fftw ("planner", method);
344 %! assert (fftw ("planner"), method);
345 %! unwind_protect_cleanup
346 %! fftw ("planner", def_method);
347 %! end_unwind_protect
348 
349 %!testif HAVE_FFTW
350 %! def_dwisdom = fftw ("dwisdom");
351 %! def_swisdom = fftw ("swisdom");
352 %! unwind_protect
353 %! wisdom = fftw ("dwisdom");
354 %! assert (ischar (wisdom));
355 %! fftw ("dwisdom", wisdom);
356 %! assert (fftw ("dwisdom"), wisdom);
357 %! wisdom = fftw ("swisdom");
358 %! assert (ischar (wisdom));
359 %! fftw ("swisdom", wisdom);
360 %! assert (fftw ("swisdom"), wisdom);
361 %! unwind_protect_cleanup
362 %! fftw ("dwisdom", def_dwisdom);
363 %! fftw ("swisdom", def_swisdom);
364 %! end_unwind_protect
365 
366 %!testif HAVE_FFTW3_THREADS
367 %! n = fftw ("threads");
368 %! unwind_protect
369 %! fftw ("threads", 3);
370 %! assert (fftw ("threads"), 3);
371 %! unwind_protect_cleanup
372 %! fftw ("threads", n);
373 %! end_unwind_protect
374 
375 %!error <Invalid call to fftw|was unavailable or disabled> fftw ()
376 %!error <Invalid call to fftw|was unavailable or disabled> fftw ("planner", "estimate", "measure")
377 %!error fftw (3)
378 %!error fftw ("invalid")
379 %!error fftw ("planner", "invalid")
380 %!error fftw ("planner", 2)
381 %!error fftw ("dwisdom", "invalid")
382 %!error fftw ("swisdom", "invalid")
383 %!error fftw ("threads", "invalid")
384 %!error fftw ("threads", -3)
385  */
OCTINTERP_API void print_usage(void)
Definition: defun.cc:52
void error(const char *fmt,...)
Definition: error.cc:570
static int threads(void)
Definition: oct-fftw.h:241
static FftwMethod method(void)
Definition: oct-fftw.h:80
JNIEnv void * args
Definition: ov-java.cc:67
static FftwMethod method(void)
Definition: oct-fftw.h:225
int nargin
Definition: graphics.cc:10115
std::string str
Definition: hash.cc:118
octave_value retval
Definition: data.cc:6294
static int threads(void)
Definition: oct-fftw.h:96
void free(void *)
ColumnVector transform(const Matrix &m, double x, double y, double z)
Definition: graphics.cc:5118
#define DEFUN_DLD(name, args_name, nargout_name, doc)
Definition: defun-dld.h:45
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
Definition: errwarn.cc:50
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))