Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/Control/Options/RNG.hpp
4 : : \copyright 2012-2015 J. Bakosi,
5 : : 2016-2018 Los Alamos National Security, LLC.,
6 : : 2019-2021 Triad National Security, LLC.
7 : : All rights reserved. See the LICENSE file for details.
8 : : \brief Random number generator options and associations
9 : : \details Random number generator options and associations
10 : : */
11 : : // *****************************************************************************
12 : : #ifndef RNGOptions_h
13 : : #define RNGOptions_h
14 : :
15 : : #include <map>
16 : :
17 : : #include <brigand/sequences/list.hpp>
18 : :
19 : : #include "WalkerBuildConfig.hpp"
20 : :
21 : : #ifdef HAS_MKL
22 : : #include <mkl_vsl_defines.h>
23 : : #endif
24 : :
25 : : #include "NoWarning/append.hpp"
26 : :
27 : : #include "Toggle.hpp"
28 : : #include "Keywords.hpp"
29 : : #include "Options/RNGSSESeqLen.hpp"
30 : : #include "PUPUtil.hpp"
31 : : #include "PrintUtil.hpp"
32 : :
33 : : namespace tk {
34 : : namespace ctr {
35 : :
36 : : //! Random number generator types
37 : : enum class RNGType : uint8_t { NO_RNG=0
38 : : #ifdef HAS_RNGSSE2
39 : : , RNGSSE_GM19
40 : : , RNGSSE_GM29
41 : : , RNGSSE_GM31
42 : : , RNGSSE_GM55
43 : : , RNGSSE_GM61
44 : : , RNGSSE_GQ581
45 : : , RNGSSE_GQ583
46 : : , RNGSSE_GQ584
47 : : , RNGSSE_MT19937
48 : : , RNGSSE_LFSR113
49 : : , RNGSSE_MRG32K3A
50 : : #endif
51 : : #ifdef HAS_MKL
52 : : , MKL_MCG31 // leap frog support
53 : : , MKL_R250
54 : : , MKL_MRG32K3A
55 : : , MKL_MCG59 // leap frog support
56 : : , MKL_WH // leap frog support
57 : : , MKL_MT19937
58 : : , MKL_MT2203
59 : : , MKL_SFMT19937
60 : : , MKL_SOBOL
61 : : , MKL_NIEDERR
62 : : // MKL VSL's abstract RNGs are for use with
63 : : // external (i.e., external to MKL or user-defined
64 : : // generator via call-back functions), disabled for
65 : : // now
66 : : //, MKL_IABSTRACT
67 : : //, MKL_DABSTRACT
68 : : //, MKL_SABSTRACT
69 : : , MKL_NONDETERM
70 : : #endif
71 : : , R123_THREEFRY
72 : : , R123_PHILOX
73 : : };
74 : :
75 : : //! \brief Pack/Unpack RNGType: forward overload to generic enum class packer
76 : 1330 : inline void operator|( PUP::er& p, RNGType& e ) { PUP::pup( p, e ); }
77 : :
78 : : //! Enum class underlying type shortcut
79 : : using RawRNGType = std::underlying_type_t< RNGType >;
80 : :
81 : : //! Return underlying type
82 : : //! \param[in] r RNG enum class value
83 : : //! \return Enum class underlying value using static_cast
84 : 317 : constexpr RawRNGType raw( RNGType r ) { return static_cast< RawRNGType >( r ); }
85 : :
86 : : //! Random number generator library types
87 : : enum class RNGLibType : uint8_t { NO_LIB=0,
88 : : MKL,
89 : : RNGSSE,
90 : : PRAND,
91 : : R123 };
92 : :
93 : : //! \brief RNG options: outsource searches to base templated on enum type
94 : : class RNG : public tk::Toggle< RNGType > {
95 : :
96 : : private:
97 : : //! Valid expected choices to make them also available at compile-time
98 : : using keywordsMKL = brigand::list<
99 : : #ifdef HAS_MKL
100 : : kw::mkl_mcg31
101 : : , kw::mkl_r250
102 : : , kw::mkl_mrg32k3a
103 : : , kw::mkl_mcg59
104 : : , kw::mkl_wh
105 : : , kw::mkl_mt19937
106 : : , kw::mkl_mt2203
107 : : , kw::mkl_sfmt19937
108 : : , kw::mkl_sobol
109 : : , kw::mkl_niederr
110 : : //, kw::mkl_iabstract
111 : : //, kw::mkl_dabstract
112 : : //, kw::mkl_sabstract
113 : : , kw::mkl_nondeterm
114 : : #endif
115 : : >;
116 : : using keywordsRNGSSE2 = brigand::list<
117 : : #ifdef HAS_RNGSSE2
118 : : kw::rngsse_gm19
119 : : , kw::rngsse_gm29
120 : : , kw::rngsse_gm31
121 : : , kw::rngsse_gm55
122 : : , kw::rngsse_gm61
123 : : , kw::rngsse_gq581
124 : : , kw::rngsse_gq583
125 : : , kw::rngsse_gq584
126 : : , kw::rngsse_mt19937
127 : : , kw::rngsse_lfsr113
128 : : , kw::rngsse_mrg32k3a
129 : : #endif
130 : : >;
131 : : using keywordsR123 = brigand::list< kw::r123_threefry
132 : : , kw::r123_philox >;
133 : :
134 : : public:
135 : : using ParamType = int;
136 : : using LibType = RNGLibType;
137 : :
138 : : using keywords =
139 : : brigand::append< keywordsMKL, keywordsRNGSSE2, keywordsR123 >;
140 : :
141 : : //! \brief Options constructor
142 : : //! \details Simply initialize in-line and pass associations to base, which
143 : : //! will handle client interactions
144 : 1704 : explicit RNG() :
145 : : tk::Toggle< RNGType >(
146 : : //! Group, i.e., options, name
147 : : "Random number generator",
148 : : //! Enums -> names
149 : 0 : { { RNGType::NO_RNG, "n/a" }
150 [ + - ]: 1704 : , { RNGType::R123_THREEFRY, kw::r123_threefry::name() }
151 [ + - ]: 3408 : , { RNGType::R123_PHILOX, kw::r123_philox::name() }
152 : : #ifdef HAS_RNGSSE2
153 [ + - ]: 3408 : , { RNGType::RNGSSE_GM19, kw::rngsse_gm19::name() }
154 [ + - ]: 3408 : , { RNGType::RNGSSE_GM29, kw::rngsse_gm29::name() }
155 [ + - ]: 3408 : , { RNGType::RNGSSE_GM31, kw::rngsse_gm31::name() }
156 [ + - ]: 3408 : , { RNGType::RNGSSE_GM55, kw::rngsse_gm55::name() }
157 [ + - ]: 3408 : , { RNGType::RNGSSE_GM61, kw::rngsse_gm61::name() }
158 [ + - ]: 3408 : , { RNGType::RNGSSE_GQ581, kw::rngsse_gq581::name() }
159 [ + - ]: 3408 : , { RNGType::RNGSSE_GQ583, kw::rngsse_gq583::name() }
160 [ + - ]: 3408 : , { RNGType::RNGSSE_GQ584, kw::rngsse_gq584::name() }
161 [ + - ]: 3408 : , { RNGType::RNGSSE_MT19937, kw::rngsse_mt19937::name() }
162 [ + - ]: 3408 : , { RNGType::RNGSSE_LFSR113, kw::rngsse_lfsr113::name() }
163 [ + - ]: 3408 : , { RNGType::RNGSSE_MRG32K3A, kw::rngsse_mrg32k3a::name() }
164 : : #endif
165 : : #ifdef HAS_MKL
166 [ + - ]: 3408 : , { RNGType::MKL_MCG31, kw::mkl_mcg31::name() }
167 [ + - ]: 3408 : , { RNGType::MKL_R250, kw::mkl_r250::name() }
168 [ + - ]: 3408 : , { RNGType::MKL_MRG32K3A, kw::mkl_mrg32k3a::name() }
169 [ + - ]: 3408 : , { RNGType::MKL_MCG59, kw::mkl_mcg59::name() }
170 [ + - ]: 3408 : , { RNGType::MKL_WH, kw::mkl_wh::name() }
171 [ + - ]: 3408 : , { RNGType::MKL_MT19937, kw::mkl_mt19937::name() }
172 [ + - ]: 3408 : , { RNGType::MKL_MT2203, kw::mkl_mt2203::name() }
173 [ + - ]: 3408 : , { RNGType::MKL_SFMT19937, kw::mkl_sfmt19937::name() }
174 [ + - ]: 3408 : , { RNGType::MKL_SOBOL, kw::mkl_sobol::name() }
175 [ + - ]: 3408 : , { RNGType::MKL_NIEDERR, kw::mkl_niederr::name() }
176 : : //, { RNGType::MKL_IABSTRACT, kw::mkl_iabstract::name() }
177 : : //, { RNGType::MKL_DABSTRACT, kw::mkl_dabstract::name() }
178 : : //, { RNGType::MKL_SABSTRACT, kw::mkl_sabstract::name() }
179 [ + - ]: 3408 : , { RNGType::MKL_NONDETERM, kw::mkl_nondeterm::name() }
180 : : #endif
181 : : },
182 : : //! keywords -> Enums
183 : 0 : { { "no_rng", RNGType::NO_RNG }
184 [ + - ]: 1704 : , { kw::r123_threefry::string(), RNGType::R123_THREEFRY }
185 [ + - ]: 3408 : , { kw::r123_philox::string(), RNGType::R123_PHILOX }
186 : : #ifdef HAS_RNGSSE2
187 [ + - ]: 3408 : , { kw::rngsse_gm19::string(), RNGType::RNGSSE_GM19 }
188 [ + - ]: 3408 : , { kw::rngsse_gm29::string(), RNGType::RNGSSE_GM29 }
189 [ + - ]: 3408 : , { kw::rngsse_gm31::string(), RNGType::RNGSSE_GM31 }
190 [ + - ]: 3408 : , { kw::rngsse_gm55::string(), RNGType::RNGSSE_GM55 }
191 [ + - ]: 3408 : , { kw::rngsse_gm61::string(), RNGType::RNGSSE_GM61 }
192 [ + - ]: 3408 : , { kw::rngsse_gq581::string(), RNGType::RNGSSE_GQ581 }
193 [ + - ]: 3408 : , { kw::rngsse_gq583::string(), RNGType::RNGSSE_GQ583 }
194 [ + - ]: 3408 : , { kw::rngsse_gq584::string(), RNGType::RNGSSE_GQ584 }
195 [ + - ]: 3408 : , { kw::rngsse_mt19937::string(), RNGType::RNGSSE_MT19937 }
196 [ + - ]: 3408 : , { kw::rngsse_lfsr113::string(), RNGType::RNGSSE_LFSR113 }
197 [ + - ]: 3408 : , { kw::rngsse_mrg32k3a::string(), RNGType::RNGSSE_MRG32K3A }
198 : : #endif
199 : : #ifdef HAS_MKL
200 [ + - ]: 3408 : , { kw::mkl_mcg31::string(), RNGType::MKL_MCG31 }
201 [ + - ]: 3408 : , { kw::mkl_r250::string(), RNGType::MKL_R250 }
202 [ + - ]: 3408 : , { kw::mkl_mrg32k3a::string(), RNGType::MKL_MRG32K3A }
203 [ + - ]: 3408 : , { kw::mkl_mcg59::string(), RNGType::MKL_MCG59 }
204 [ + - ]: 3408 : , { kw::mkl_wh::string(), RNGType::MKL_WH }
205 [ + - ]: 3408 : , { kw::mkl_mt19937::string(), RNGType::MKL_MT19937 }
206 [ + - ]: 3408 : , { kw::mkl_mt2203::string(), RNGType::MKL_MT2203 }
207 [ + - ]: 3408 : , { kw::mkl_sfmt19937::string(), RNGType::MKL_SFMT19937 }
208 [ + - ]: 3408 : , { kw::mkl_sobol::string(), RNGType::MKL_SOBOL }
209 [ + - ]: 3408 : , { kw::mkl_niederr::string(), RNGType::MKL_NIEDERR }
210 : : //, { kw::mkl_iabstract::string(), RNGType::MKL_IABSTRACT }
211 : : //, { kw::mkl_dabstract::string(), RNGType::MKL_DABSTRACT }
212 : : //, { kw::mkl_sabstract::string(), RNGType::MKL_SABSTRACT }
213 [ + - ]: 3408 : , { kw::mkl_nondeterm::string(), RNGType::MKL_NONDETERM }
214 : : #endif
215 [ + - ][ + - ]: 201072 : } ) {}
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ - - ]
[ - - ][ - - ]
216 : :
217 : : //! \brief Return parameter based on Enum
218 : : //! \details Here 'parameter' is the library-specific identifier of the
219 : : //! option, i.e., as the library identifies the given option
220 : : //! \param[in] rng Enum value of the option requested
221 : : //! \return Library-specific parameter of the option
222 : 3273 : const ParamType& param( RNGType rng ) const {
223 : : using tk::operator<<;
224 [ + - ]: 3273 : auto it = brng.find( rng );
225 [ + + ][ + - ]: 3273 : Assert( it != end(brng),
[ + - ][ + - ]
[ + - ][ + - ]
226 : : std::string("Cannot find parameter for RNG \"") << rng << "\"" );
227 : 3272 : return it->second;
228 : : }
229 : :
230 : : //! \brief Return field from RNG parameters bundle
231 : : //! \details If user has specified it, return field. If user did not
232 : : //! specify it, return default.
233 : : //! \param[in] rng Enum value of the option
234 : : //! \param[in] def Default value of requested field if field is not found
235 : : //! \param[in] bundle Parameter bundle to search in
236 : : //! \return Field for requested enum if found, default if not found
237 : : template< class tag, class Param, class Field >
238 : 22574 : Field param( RNGType rng, const Field& def, const Param& bundle ) const {
239 [ + - ]: 22574 : auto it = bundle.find( rng );
240 [ + + ]: 22574 : if ( it != bundle.end() ) return it->second.template get< tag >();
241 : 22205 : else return def;
242 : : }
243 : :
244 : : //! \brief Return RNG library type based on RNG options enum
245 : : //! \param[in] rng Enum value of the option
246 : : //! \return Library type enum
247 : : //! \see tk::ctr::RNGLibType
248 : 39 : RNGLibType lib( RNGType rng ) const {
249 : 39 : const auto& n = name( rng );
250 [ + - ][ + + ]: 39 : if ( found( "MKL", n ) ) return RNGLibType::MKL;
251 [ + - ][ + + ]: 26 : else if ( found( "RNGSSE", n ) ) return RNGLibType::RNGSSE;
252 [ + - ][ - + ]: 10 : else if ( found( "PRAND", n ) ) return RNGLibType::PRAND;
253 [ + - ][ + - ]: 10 : else if ( found( "Random123", n ) ) return RNGLibType::R123;
254 : 0 : else return RNGLibType::NO_LIB;
255 : : }
256 : :
257 : : //! \brief Return whether RNG supports sequence option
258 : : //! \param[in] rng Enum value of the option
259 : : //! \return True if RNG supports sequence option
260 : 7 : bool supportsSeq( RNGType rng ) const
261 [ + - ]: 7 : { return support.find( rng ) != end( support ) ? true : false; }
262 : :
263 : : //! \brief Return whether RNG supports sequence option given
264 : : //! \param[in] rng Enum value of the option
265 : : //! \param[in] option Option type
266 : : //! \return True if RNG supports sequence option
267 : : template< class OptionType >
268 : 1 : bool supportsOpt( RNGType rng, const OptionType& option ) const {
269 [ + - ]: 1 : auto it = support.find( rng );
270 [ + - ]: 1 : if ( it != end( support ) ) {
271 [ + - ]: 2 : for (auto o : it->second)
272 : : // cppcheck-suppress useStlAlgorithm
273 [ + + ]: 2 : if (o == option) return true;
274 : : }
275 : 0 : return false;
276 : : }
277 : :
278 : : private:
279 : : //! \brief Search for 'kw' in 'str'
280 : : //! \param[in] kw Keyword to search for
281 : : //! \param[in] str String to search in
282 : : //! \return True if found, false if not
283 : 85 : bool found( const std::string& kw, const std::string& str ) const
284 : 85 : { return str.find( kw ) != std::string::npos ? true : false; }
285 : :
286 : : //! Enums -> MKL VSL BRNG parameters
287 : : std::map< RNGType, ParamType > brng {
288 : : { RNGType::NO_RNG, -1 }
289 : : , { RNGType::R123_THREEFRY, 0 }
290 : : , { RNGType::R123_PHILOX, 1 }
291 : : #ifdef HAS_RNGSSE2
292 : : , { RNGType::RNGSSE_GM19, 2 }
293 : : , { RNGType::RNGSSE_GM29, 3 }
294 : : , { RNGType::RNGSSE_GM31, 4 }
295 : : , { RNGType::RNGSSE_GM55, 5 }
296 : : , { RNGType::RNGSSE_GM61, 6 }
297 : : , { RNGType::RNGSSE_GQ581, 7 }
298 : : , { RNGType::RNGSSE_GQ583, 8 }
299 : : , { RNGType::RNGSSE_GQ584, 9 }
300 : : , { RNGType::RNGSSE_MT19937, 10 }
301 : : , { RNGType::RNGSSE_LFSR113, 11 }
302 : : , { RNGType::RNGSSE_MRG32K3A, 12 }
303 : : #endif
304 : : #ifdef HAS_MKL
305 : : , { RNGType::MKL_MCG31, VSL_BRNG_MCG31 }
306 : : , { RNGType::MKL_R250, VSL_BRNG_R250 }
307 : : , { RNGType::MKL_MRG32K3A, VSL_BRNG_MRG32K3A }
308 : : , { RNGType::MKL_MCG59, VSL_BRNG_MCG59 }
309 : : , { RNGType::MKL_WH, VSL_BRNG_WH }
310 : : , { RNGType::MKL_MT19937, VSL_BRNG_MT19937 }
311 : : , { RNGType::MKL_MT2203, VSL_BRNG_MT2203 }
312 : : , { RNGType::MKL_SFMT19937, VSL_BRNG_SFMT19937 }
313 : : , { RNGType::MKL_SOBOL, VSL_BRNG_SOBOL }
314 : : , { RNGType::MKL_NIEDERR, VSL_BRNG_NIEDERR }
315 : : //, { RNGType::MKL_IABSTRACT, VSL_BRNG_IABSTRACT }
316 : : //, { RNGType::MKL_DABSTRACT, VSL_BRNG_DABSTRACT }
317 : : //, { RNGType::MKL_SABSTRACT, VSL_BRNG_SABSTRACT }
318 : : , { RNGType::MKL_NONDETERM, VSL_BRNG_NONDETERM }
319 : : #endif
320 : 1704 : };
321 : :
322 : : //! Enums -> sequence length options supported
323 : : std::map< RNGType, std::vector< RNGSSESeqLenType > > support {
324 : : #ifdef HAS_RNGSSE2
325 : 1704 : { RNGType::RNGSSE_GM29, { RNGSSESeqLenType::SHORT,
326 : : RNGSSESeqLenType::MEDIUM,
327 : : RNGSSESeqLenType::LONG } },
328 : 1704 : { RNGType::RNGSSE_GM31, { RNGSSESeqLenType::SHORT,
329 : : RNGSSESeqLenType::MEDIUM,
330 : : RNGSSESeqLenType::LONG } },
331 : 1704 : { RNGType::RNGSSE_GM55, { RNGSSESeqLenType::SHORT,
332 : : RNGSSESeqLenType::LONG } },
333 : 1704 : { RNGType::RNGSSE_GQ581, { RNGSSESeqLenType::SHORT,
334 : : RNGSSESeqLenType::MEDIUM,
335 : : RNGSSESeqLenType::LONG } },
336 : 1704 : { RNGType::RNGSSE_GQ583, { RNGSSESeqLenType::SHORT,
337 : : RNGSSESeqLenType::MEDIUM,
338 : : RNGSSESeqLenType::LONG } },
339 : 1704 : { RNGType::RNGSSE_GQ584, { RNGSSESeqLenType::SHORT,
340 : : RNGSSESeqLenType::MEDIUM,
341 : : RNGSSESeqLenType::LONG } },
342 : 1704 : { RNGType::RNGSSE_GM61, { RNGSSESeqLenType::SHORT,
343 : : RNGSSESeqLenType::LONG } },
344 : 1704 : { RNGType::RNGSSE_LFSR113, { RNGSSESeqLenType::SHORT,
345 : : RNGSSESeqLenType::LONG } }
346 : : #endif
347 : 3408 : };
348 : : };
349 : :
350 : : } // ctr::
351 : : } // tk::
352 : :
353 : : #endif // RNGOptions_h
|