Quinoa unit test code coverage report
Current view: top level - Control/Options - RNG.hpp (source / functions) Hit Total Coverage
Commit: Quinoa_v0.3-957-gb4f0efae0 Lines: 34 35 97.1 %
Date: 2021-11-09 12:13:43 Functions: 2 2 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 63 190 33.2 %

           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 "QuinoaBuildConfig.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                 :            : 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                 :            : 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                 :         82 :     explicit RNG() :
     145                 :            :       tk::Toggle< RNGType >(
     146                 :            :         //! Group, i.e., options, name
     147                 :            :         "Random number generator",
     148                 :            :         //! Enums -> names
     149                 :            :         { { RNGType::NO_RNG, "n/a" }
     150                 :         82 :         , { RNGType::R123_THREEFRY, kw::r123_threefry::name() }
     151 [ -  + ][ -  - ]:         82 :         , { RNGType::R123_PHILOX, kw::r123_philox::name() }
     152                 :            :         #ifdef HAS_RNGSSE2
     153 [ -  + ][ -  - ]:         82 :         , { RNGType::RNGSSE_GM19, kw::rngsse_gm19::name() }
     154 [ -  + ][ -  - ]:         82 :         , { RNGType::RNGSSE_GM29, kw::rngsse_gm29::name() }
     155 [ -  + ][ -  - ]:         82 :         , { RNGType::RNGSSE_GM31, kw::rngsse_gm31::name() }
     156 [ -  + ][ -  - ]:         82 :         , { RNGType::RNGSSE_GM55, kw::rngsse_gm55::name() }
     157 [ -  + ][ -  - ]:         82 :         , { RNGType::RNGSSE_GM61, kw::rngsse_gm61::name() }
     158 [ -  + ][ -  - ]:         82 :         , { RNGType::RNGSSE_GQ581, kw::rngsse_gq581::name() }
     159 [ -  + ][ -  - ]:         82 :         , { RNGType::RNGSSE_GQ583, kw::rngsse_gq583::name() }
     160 [ -  + ][ -  - ]:         82 :         , { RNGType::RNGSSE_GQ584, kw::rngsse_gq584::name() }
     161 [ -  + ][ -  - ]:         82 :         , { RNGType::RNGSSE_MT19937, kw::rngsse_mt19937::name() }
     162 [ -  + ][ -  - ]:         82 :         , { RNGType::RNGSSE_LFSR113, kw::rngsse_lfsr113::name() }
     163 [ -  + ][ -  - ]:         82 :         , { RNGType::RNGSSE_MRG32K3A, kw::rngsse_mrg32k3a::name() }
     164                 :            :         #endif
     165                 :            :         #ifdef HAS_MKL
     166                 :            :         , { RNGType::MKL_MCG31, kw::mkl_mcg31::name() }
     167                 :            :         , { RNGType::MKL_R250, kw::mkl_r250::name() }
     168                 :            :         , { RNGType::MKL_MRG32K3A, kw::mkl_mrg32k3a::name() }
     169                 :            :         , { RNGType::MKL_MCG59, kw::mkl_mcg59::name() }
     170                 :            :         , { RNGType::MKL_WH, kw::mkl_wh::name() }
     171                 :            :         , { RNGType::MKL_MT19937, kw::mkl_mt19937::name() }
     172                 :            :         , { RNGType::MKL_MT2203, kw::mkl_mt2203::name() }
     173                 :            :         , { RNGType::MKL_SFMT19937, kw::mkl_sfmt19937::name() }
     174                 :            :         , { RNGType::MKL_SOBOL, kw::mkl_sobol::name() }
     175                 :            :         , { 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                 :            :         , { RNGType::MKL_NONDETERM, kw::mkl_nondeterm::name() }
     180                 :            :         #endif
     181                 :            :         },
     182                 :            :         //! keywords -> Enums
     183                 :            :         { { "no_rng", RNGType::NO_RNG }
     184                 :         82 :         , { kw::r123_threefry::string(), RNGType::R123_THREEFRY }
     185 [ -  + ][ -  - ]:         82 :         , { kw::r123_philox::string(), RNGType::R123_PHILOX }
     186                 :            :         #ifdef HAS_RNGSSE2
     187 [ -  + ][ -  - ]:         82 :         , { kw::rngsse_gm19::string(), RNGType::RNGSSE_GM19 }
     188 [ -  + ][ -  - ]:         82 :         , { kw::rngsse_gm29::string(), RNGType::RNGSSE_GM29 }
     189 [ -  + ][ -  - ]:         82 :         , { kw::rngsse_gm31::string(), RNGType::RNGSSE_GM31 }
     190 [ -  + ][ -  - ]:         82 :         , { kw::rngsse_gm55::string(), RNGType::RNGSSE_GM55 }
     191 [ -  + ][ -  - ]:         82 :         , { kw::rngsse_gm61::string(), RNGType::RNGSSE_GM61 }
     192 [ -  + ][ -  - ]:         82 :         , { kw::rngsse_gq581::string(), RNGType::RNGSSE_GQ581 }
     193 [ -  + ][ -  - ]:         82 :         , { kw::rngsse_gq583::string(), RNGType::RNGSSE_GQ583 }
     194 [ -  + ][ -  - ]:         82 :         , { kw::rngsse_gq584::string(), RNGType::RNGSSE_GQ584 }
     195 [ -  + ][ -  - ]:         82 :         , { kw::rngsse_mt19937::string(), RNGType::RNGSSE_MT19937 }
     196 [ -  + ][ -  - ]:         82 :         , { kw::rngsse_lfsr113::string(), RNGType::RNGSSE_LFSR113 }
     197 [ -  + ][ -  - ]:         82 :         , { kw::rngsse_mrg32k3a::string(), RNGType::RNGSSE_MRG32K3A }
     198                 :            :         #endif
     199                 :            :         #ifdef HAS_MKL
     200                 :            :         , { kw::mkl_mcg31::string(), RNGType::MKL_MCG31 }
     201                 :            :         , { kw::mkl_r250::string(), RNGType::MKL_R250 }
     202                 :            :         , { kw::mkl_mrg32k3a::string(), RNGType::MKL_MRG32K3A }
     203                 :            :         , { kw::mkl_mcg59::string(), RNGType::MKL_MCG59 }
     204                 :            :         , { kw::mkl_wh::string(), RNGType::MKL_WH }
     205                 :            :         , { kw::mkl_mt19937::string(), RNGType::MKL_MT19937 }
     206                 :            :         , { kw::mkl_mt2203::string(), RNGType::MKL_MT2203 }
     207                 :            :         , { kw::mkl_sfmt19937::string(), RNGType::MKL_SFMT19937 }
     208                 :            :         , { kw::mkl_sobol::string(), RNGType::MKL_SOBOL }
     209                 :            :         , { 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                 :            :         , { kw::mkl_nondeterm::string(), RNGType::MKL_NONDETERM }
     214                 :            :         #endif
     215 [ +  - ][ +  - ]:       4756 :         } ) {}
         [ +  - ][ +  + ]
         [ +  + ][ -  + ]
         [ +  + ][ -  + ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
     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                 :            :     const ParamType& param( RNGType rng ) const {
     223                 :            :       using tk::operator<<;
     224                 :            :       auto it = brng.find( rng );
     225                 :            :       Assert( it != end(brng),
     226                 :            :               std::string("Cannot find parameter for RNG \"") << rng << "\"" );
     227                 :            :       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                 :            :     Field param( RNGType rng, const Field& def, const Param& bundle ) const {
     239                 :            :       auto it = bundle.find( rng );
     240         [ +  - ]:          1 :       if ( it != bundle.end() ) return it->second.template get< tag >();
     241                 :            :       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                 :          2 :     RNGLibType lib( RNGType rng ) const {
     249                 :            :       const auto& n = name( rng );
     250         [ +  - ]:          4 :       if ( found( "MKL", n ) ) return RNGLibType::MKL;
     251         [ +  + ]:          4 :       else if ( found( "RNGSSE", n ) ) return RNGLibType::RNGSSE;
     252         [ +  - ]:          2 :       else if ( found( "PRAND", n ) ) return RNGLibType::PRAND;
     253         [ -  + ]:          2 :       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                 :            :     bool supportsSeq( RNGType rng ) const
     261                 :            :     { 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                 :            :     bool supportsOpt( RNGType rng, const OptionType& option ) const {
     269                 :            :       auto it = support.find( rng );
     270                 :            :       if ( it != end( support ) ) {
     271                 :            :         for (auto o : it->second)
     272                 :            :           // cppcheck-suppress useStlAlgorithm
     273                 :            :           if (o == option) return true;
     274                 :            :       }
     275                 :            :       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                 :            :     bool found( const std::string& kw, const std::string& str ) const
     284                 :            :     { 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                 :            :     };
     321                 :            : 
     322                 :            :     //! Enums -> sequence length options supported
     323                 :            :     std::map< RNGType, std::vector< RNGSSESeqLenType > > support {
     324                 :            :       #ifdef HAS_RNGSSE2
     325                 :            :       { RNGType::RNGSSE_GM29,    { RNGSSESeqLenType::SHORT,
     326                 :            :                                    RNGSSESeqLenType::MEDIUM,
     327                 :            :                                    RNGSSESeqLenType::LONG } },
     328                 :            :       { RNGType::RNGSSE_GM31,    { RNGSSESeqLenType::SHORT,
     329                 :            :                                    RNGSSESeqLenType::MEDIUM,
     330                 :            :                                    RNGSSESeqLenType::LONG } },
     331                 :            :       { RNGType::RNGSSE_GM55,    { RNGSSESeqLenType::SHORT,
     332                 :            :                                    RNGSSESeqLenType::LONG } },
     333                 :            :       { RNGType::RNGSSE_GQ581,   { RNGSSESeqLenType::SHORT,
     334                 :            :                                    RNGSSESeqLenType::MEDIUM,
     335                 :            :                                    RNGSSESeqLenType::LONG } },
     336                 :            :       { RNGType::RNGSSE_GQ583,   { RNGSSESeqLenType::SHORT,
     337                 :            :                                    RNGSSESeqLenType::MEDIUM,
     338                 :            :                                    RNGSSESeqLenType::LONG } },
     339                 :            :       { RNGType::RNGSSE_GQ584,   { RNGSSESeqLenType::SHORT,
     340                 :            :                                    RNGSSESeqLenType::MEDIUM,
     341                 :            :                                    RNGSSESeqLenType::LONG } },
     342                 :            :       { RNGType::RNGSSE_GM61,    { RNGSSESeqLenType::SHORT,
     343                 :            :                                    RNGSSESeqLenType::LONG } },
     344                 :            :       { RNGType::RNGSSE_LFSR113, { RNGSSESeqLenType::SHORT,
     345                 :            :                                    RNGSSESeqLenType::LONG } }
     346                 :            :       #endif
     347                 :            :     };
     348                 :            : };
     349                 :            : 
     350                 :            : } // ctr::
     351                 :            : } // tk::
     352                 :            : 
     353                 :            : #endif // RNGOptions_h

Generated by: LCOV version 1.14