Line data Source code
1 : /** \file fftwEnvironment.hpp
2 : * \brief Declares and defines the fftwEnvironment manager
3 : * \ingroup ft_files
4 : * \author Jared R. Males (jaredmales@gmail.com)
5 : *
6 : */
7 :
8 : //***********************************************************************//
9 : // Copyright 2015-2015 Jared R. Males (jaredmales@gmail.com)
10 : //
11 : // This file is part of mxlib.
12 : //
13 : // mxlib is free software: you can redistribute it and/or modify
14 : // it under the terms of the GNU General Public License as published by
15 : // the Free Software Foundation, either version 3 of the License, or
16 : // (at your option) any later version.
17 : //
18 : // mxlib is distributed in the hope that it will be useful,
19 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 : // GNU General Public License for more details.
22 : //
23 : // You should have received a copy of the GNU General Public License
24 : // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25 : //***********************************************************************//
26 :
27 : #ifndef fftwEnvironment_hpp
28 : #define fftwEnvironment_hpp
29 :
30 : #include <string>
31 :
32 : #include "../../sys/environment.hpp"
33 :
34 : #include "fftwTemplates.hpp"
35 :
36 : namespace mx
37 : {
38 : namespace math
39 : {
40 : namespace ft
41 : {
42 :
43 : /** \addtogroup fftw_env
44 :
45 : mxlib will manage the FFTW environment for you, which really means importing and exporting
46 : wisdom and cleaning up memory. This can be done in a simple way using
47 : \ref mx::math::ft::fftwEnvironment.
48 : To make the best use of this, create a directory to store FFTW wisdom. The typical choice is
49 : `$(HOME)/.fftw`
50 :
51 : Then add the environment variable to your bash profile (i.e. in `.bash_profile` or `.bash_aliases`) as so
52 : \verbatim
53 : export MXFFTW_WISDOM=/path/to/.fftw
54 : \endverbatim
55 :
56 : Using this facility requires only that you create an object of type \ref mx::math::ft::fftwEnvironment
57 : at the beginning of the program for the real floating point type you are using. E.g.:
58 : \code
59 :
60 : #include <mx/fft/fftwEnvironment.hpp>
61 :
62 : int main()
63 : {
64 : typedef double realT;
65 : mx::math::ft::fftwEnvironment<realT> fftwEnv;
66 :
67 : //do stuff . . .
68 :
69 : return 0;
70 : }
71 : \endcode
72 :
73 : See the documentation for \ref mx::math::ft::fftwEnvironment for details.
74 :
75 : */
76 :
77 : /// Return a string corresponding the fftw real floating point type.
78 : /** This is used for wisdom filenames.
79 : *
80 : * \tparam realT the real floating point type.
81 : *
82 : * \ingroup fftw_env
83 : */
84 : template <typename realT>
85 : std::string fftw_typename();
86 :
87 : template <>
88 : std::string fftw_typename<float>();
89 :
90 : template <>
91 : std::string fftw_typename<double>();
92 :
93 : template <>
94 : std::string fftw_typename<long double>();
95 :
96 : #ifdef HASQUAD
97 : template <>
98 : std::string fftw_typename<__float128>();
99 : #endif
100 :
101 : /// Create the mxlib standard wisdom filename for the type.
102 : /** Looks for the environment variable MXFFTW_WISDOM. If not found, then pwd "./" is used.
103 : *
104 : * \tparam realT is the real floating point type.
105 : *
106 : * \ingroup fftw_env
107 : */
108 : template <typename realT>
109 36 : std::string fftw_wisdom_filename()
110 : {
111 72 : std::string path = sys::getEnv( "MXFFTW_WISDOM" );
112 36 : std::string sub = "fftw_wisdom.";
113 :
114 36 : if( path == "" )
115 : {
116 18 : path = ".";
117 18 : sub = ".fftw_wisdom.";
118 : }
119 :
120 36 : std::string filename = path + "/" + sub + fftw_typename<realT>();
121 :
122 36 : return filename;
123 36 : }
124 :
125 : /// Manage the FFTW environment and wisdom using RAII
126 : /** This class manages the FFTW environment. On construction, wisdom is imported from the
127 : * mxlib standard location, and if threads are used threading is initialized and planners are made thread safe.
128 : *
129 : * \note the fftw docs recommend against using fftw_make_planner_thread_safe. It does seem to play poorly with omp.
130 : *
131 : * On destruction, wisdom is exported and the fftw_cleanup[_threads] function is called.
132 : *
133 : * Typically, an object of this type should be created in the main function. Nothing else needs to be done with it,
134 : * as it will be destructed on program termination. Example:
135 : \code
136 :
137 : #include <mx/fft/fftwEnvironment.hpp>
138 :
139 : int main()
140 : {
141 : typedef double realT;
142 : mx::math::ft::fftwEnvironment<realT> fftwEnv;
143 :
144 : //do stuff . . .
145 :
146 : return 0;
147 : }
148 : \endcode
149 : * Note that there is no need to explicitly destroy the object fftwEnv.
150 : *
151 : * \ingroup fftw_env
152 : */
153 : template <typename realT, bool threads = false>
154 : struct fftwEnvironment
155 : {
156 : /// Constructor
157 6 : explicit fftwEnvironment(unsigned nThreads = 0 /**< [in] [optional] the number of threads to use. This can be changed any time by the program by calling \ref fftw_plan_with_nthreads() */)
158 : {
159 : static_cast<void>( nThreads );
160 6 : errno = 0;
161 6 : int rv = fftw_import_wisdom_from_filename<realT>( fftw_wisdom_filename<realT>().c_str() );
162 6 : }
163 :
164 : /// Destructor
165 6 : ~fftwEnvironment()
166 : {
167 6 : errno = 0;
168 6 : int rv = fftw_export_wisdom_to_filename<realT>( fftw_wisdom_filename<realT>().c_str() );
169 :
170 6 : fftw_cleanup<realT>();
171 6 : }
172 : };
173 :
174 : // Partial specialization for threads.
175 : template <typename realT>
176 : struct fftwEnvironment<realT, true>
177 : {
178 : /// Constructor
179 6 : explicit fftwEnvironment(unsigned nThreads = 1 /**< [in] [optional] the number of threads to use.
180 : This can be changed any time by the program by calling
181 : \ref fftw_plan_with_nthreads() */)
182 : {
183 6 : fftw_make_planner_thread_safe<realT>();
184 :
185 6 : if( nThreads == 0 )
186 : {
187 0 : nThreads = 1; // Just to be safe, 1 disables threads but the fftw docs don't say what happens for 0.
188 : }
189 :
190 6 : fftw_plan_with_nthreads<realT>( nThreads );
191 :
192 6 : fftw_import_wisdom_from_filename<realT>( fftw_wisdom_filename<realT>().c_str() );
193 6 : }
194 :
195 : /// Destructor
196 6 : ~fftwEnvironment()
197 : {
198 6 : fftw_export_wisdom_to_filename<realT>( fftw_wisdom_filename<realT>().c_str() );
199 :
200 6 : fftw_cleanup_threads<realT>();
201 6 : }
202 : };
203 :
204 : } // namespace ft
205 : } // namespace math
206 : } // namespace mx
207 :
208 : #endif // fftwEnvironment_hpp
|