LCOV - code coverage report
Current view: top level - math - randomT.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 100.0 % 32 32
Test Date: 2026-02-19 16:58:26 Functions: 100.0 % 10 10

            Line data    Source code
       1              : /** \file randomT.hpp
       2              :  * \author Jared R. Males
       3              :  * \brief Defines a random number type
       4              :  * \ingroup gen_math_files
       5              :  *
       6              :  */
       7              : 
       8              : //***********************************************************************//
       9              : // Copyright 2015, 2016, 2017, 2020 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 mx_math_randomT_hpp
      28              : #define mx_math_randomT_hpp
      29              : 
      30              : #include <random>
      31              : 
      32              : #include "randomSeed.hpp"
      33              : 
      34              : namespace mx
      35              : {
      36              : namespace math
      37              : {
      38              : 
      39              : /// A random number type, which functions like any other arithmetic type.
      40              : /**
      41              :   * Combines a random engine, and a random distribution.  Using the type conversion operator
      42              :   * randomT returns the next random deviate whenever it is referenced.
      43              :   *
      44              :   * Example:
      45              :   *
      46              :     \code
      47              :     //This can also be done using the alias definition mx::math::normDistT.
      48              :     randomT<double, std::mt19937_64, std::normal_distribution<double> > norm_distd;
      49              :     norm_distd.seed(); //
      50              : 
      51              :     double d1 = norm_distd; //get a normally distributed value
      52              :     double d2 = norm_distd; //get the next normally distributed value
      53              :    \endcode
      54              :   *
      55              :   * Tests:
      56              :   *     - Verify compilation and basic operation of randomT with std::distributions \ref tests_math_randomT_basic "[test doc]"
      57              :   *     - Verify compilation and basic operation of randomT with the Laplace distribution \ref
      58              :   tests_math_randomT_basic_laplace "[test doc]"
      59              :   *
      60              :   * \ingroup random
      61              :   */
      62              : template <class typeT, class _ranengT, class _randistT>
      63              : class randomT
      64              : {
      65              : 
      66              :   public:
      67              :     /// Typedef for the distribution type
      68              :     typedef _randistT randistT;
      69              : 
      70              :     /// Typedef for the engine type
      71              :     typedef _ranengT ranengT;
      72              : 
      73              :     /// Constructor
      74              :     /** By default this calls the seed method, which will use /dev/random to seed the generator on linux, and time(0) on
      75              :      * other systems. Set to false to suppress seeding, and/or set a seed with seed(x).
      76              :      */
      77           21 :     randomT( bool doSeed = true /**< [in] [optional] if true then the seed method is called upon construction.*/ )
      78           26 :     {
      79           21 :         if( doSeed )
      80              :         {
      81            9 :             seed();
      82              :         }
      83           21 :     }
      84              : 
      85              :     /// The random distribution
      86              :     _randistT distribution;
      87              : 
      88              :     /// The random engine
      89              :     ranengT engine;
      90              : 
      91              :     /// The conversion operator, returns the next value in the sequence, according to the distribution.
      92     14540818 :     operator typeT()
      93              :     {
      94     14540818 :         return distribution( engine );
      95              :     }
      96              : 
      97              :     /// Set the seed of the random engine.
      98              :     /** Calls the engines seed member function.
      99              :      *
     100              :      */
     101           21 :     void seed( typename ranengT::result_type seedval /**< [in] the argument to pass to ranengT::seed() */ )
     102              :     {
     103           21 :         engine.seed( seedval );
     104           21 :     }
     105              : 
     106              :     /// Seed the random engine with a good value
     107              :     /** Calls \ref mx::randomSeed to get the value.  On linux this uses /dev/urandom.  On other sytems, this uses
     108              :      * time(0).
     109              :      */
     110            9 :     void seed()
     111              :     {
     112              :         typename ranengT::result_type seedval;
     113            9 :         randomSeed( seedval );
     114            9 :         seed( seedval );
     115            9 :     }
     116              : };
     117              : 
     118              : /**
     119              :  * @brief The Laplace (double exponential) continuous distribution for random numbers.
     120              :  *
     121              :  * The formula for the exponential probability density function is
     122              :  * @f$p(x|\lambda) = \frac{\lambda}{2} e^{-\lambda x}@f$.
     123              :  *
     124              :  * <table border=1 cellpadding=10 cellspacing=0>
     125              :  * <caption align=top>Distribution Statistics</caption>
     126              :  * <tr><td>Mean</td><td>@f$0@f$</td></tr>
     127              :  * <tr><td>Median</td><td>@f$0@f$</td></tr>
     128              :  * <tr><td>Mode</td><td>@f$0@f$</td></tr>
     129              :  * <tr><td>Range</td><td>@f$[-\infty, \infty]@f$</td></tr>
     130              :  * <tr><td>Standard Deviation</td><td>@f$\frac{\sqrt{2}}{\lambda}@f$</td></tr>
     131              :  * </table>
     132              :  *
     133              :  * This is based on the implementation of the exponential distribution in the GNU ISO C++ Library version 4.6.
     134              :  *
     135              :  * Tests:
     136              :  *     - Verify compilation and basic operation of randomT with the Laplace distribution \ref tests_math_randomT_basic_laplace "[test doc]"
     137              :  *     -
     138              :  * \ingroup random
     139              :  */
     140              : template <typename _RealType = double>
     141              : class laplace_distribution
     142              : {
     143              :     static_assert( std::is_floating_point<_RealType>::value, "template argument not a floating point type" );
     144              : 
     145              :   public:
     146              :     /** The type of the range of the distribution. */
     147              :     typedef _RealType result_type;
     148              : 
     149              :     /** Parameter type. */
     150              :     struct param_type
     151              :     {
     152              :         typedef laplace_distribution<_RealType> distribution_type;
     153              : 
     154            5 :         explicit param_type( _RealType __lambda = _RealType( 1 ) ) : _M_lambda( __lambda )
     155              :         {
     156            5 :         }
     157              : 
     158            6 :         _RealType lambda() const
     159              :         {
     160            6 :             return _M_lambda;
     161              :         }
     162              : 
     163              :         friend bool operator==( const param_type &__p1, const param_type &__p2 )
     164              :         {
     165              :             return __p1._M_lambda == __p2._M_lambda;
     166              :         }
     167              : 
     168              :       private:
     169              :         _RealType _M_lambda;
     170              :     };
     171              : 
     172              :   public:
     173              :     /**
     174              :      * @brief Constructs a Laplace (double exponential) distribution with inverse scale
     175              :      *        parameter @f$\lambda@f$.
     176              :      */
     177           10 :     explicit laplace_distribution( const result_type &__lambda = result_type( 1 ) ) : _M_param( __lambda )
     178              :     {
     179            5 :     }
     180              : 
     181              :     explicit laplace_distribution( const param_type &__p ) : _M_param( __p )
     182              :     {
     183              :     }
     184              : 
     185              :     /**
     186              :      * @brief Resets the distribution state.
     187              :      *
     188              :      * Has no effect on Laplace distributions.
     189              :      */
     190              :     void reset()
     191              :     {
     192              :     }
     193              : 
     194              :     /**
     195              :      * @brief Returns the inverse scale parameter of the distribution.
     196              :      */
     197              :     _RealType lambda() const
     198              :     {
     199              :         return _M_param.lambda();
     200              :     }
     201              : 
     202              :     /**
     203              :      * @brief Returns the parameter set of the distribution.
     204              :      */
     205            6 :     param_type param() const
     206              :     {
     207            6 :         return _M_param;
     208              :     }
     209              : 
     210              :     /**
     211              :      * @brief Sets the parameter set of the distribution.
     212              :      * @param __param The new parameter set of the distribution.
     213              :      */
     214              :     void param( const param_type &__param )
     215              :     {
     216              :         _M_param = __param;
     217              :     }
     218              : 
     219              :     /**
     220              :      * @brief Returns the greatest lower bound value of the distribution.
     221              :      */
     222              :     result_type min() const
     223              :     {
     224              :         return std::numeric_limits<result_type>::min();
     225              :     }
     226              : 
     227              :     /**
     228              :      * @brief Returns the least upper bound value of the distribution.
     229              :      */
     230              :     result_type max() const
     231              :     {
     232              :         return std::numeric_limits<result_type>::max();
     233              :     }
     234              : 
     235              :     /**
     236              :      * @brief Generating functions.
     237              :      */
     238              :     template <typename _UniformRandomNumberGenerator>
     239            6 :     result_type operator()( _UniformRandomNumberGenerator &__urng )
     240              :     {
     241            6 :         return this->operator()( __urng, this->param() );
     242              :     }
     243              : 
     244              :     template <typename _UniformRandomNumberGenerator>
     245            6 :     result_type operator()( _UniformRandomNumberGenerator &__urng, const param_type &__p )
     246              :     {
     247            6 :         int sgnx = 1;
     248              : 
     249            6 :         result_type __aurng = 0.5 - std::generate_canonical<result_type,
     250              :                                                             std::numeric_limits<result_type>::digits,
     251            6 :                                                             _UniformRandomNumberGenerator>( __urng );
     252              : 
     253            6 :         if( __aurng < 0 )
     254              :         {
     255            3 :             sgnx = -1;
     256            3 :             __aurng *= -1;
     257              :         }
     258              : 
     259            6 :         return 0. - __p.lambda() * sgnx * std::log( 1. - 2. * __aurng );
     260              :     }
     261              : 
     262              :   private:
     263              :     param_type _M_param;
     264              : };
     265              : 
     266              : /**
     267              :  * @brief Return true if two exponential distributions have the same
     268              :  *        parameters.
     269              :  */
     270              : template <typename _RealType>
     271              : bool operator==( const laplace_distribution<_RealType> &__d1, const laplace_distribution<_RealType> &__d2 )
     272              : {
     273              :     return __d1.param() == __d2.param();
     274              : }
     275              : 
     276              : /**
     277              :  * @brief Return true if two exponential distributions have different
     278              :  *        parameters.
     279              :  */
     280              : template <typename _RealType>
     281              : bool operator!=( const laplace_distribution<_RealType> &__d1, const laplace_distribution<_RealType> &__d2 )
     282              : {
     283              :     return !( __d1 == __d2 );
     284              : }
     285              : 
     286              : /**
     287              :  * @brief Inserts a %laplace_distribution random number distribution
     288              :  * @p __x into the output stream @p __os.
     289              :  *
     290              :  * @param __os An output stream.
     291              :  * @param __x  A %laplace_distribution random number distribution.
     292              :  *
     293              :  * @returns The output stream with the state of @p __x inserted or in
     294              :  * an error state.
     295              :  */
     296              : template <typename _RealType, typename _CharT, typename _Traits>
     297              : std::basic_ostream<_CharT, _Traits> &operator<<( std::basic_ostream<_CharT, _Traits> &,
     298              :                                                  const laplace_distribution<_RealType> & );
     299              : 
     300              : /**
     301              :  * @brief Extracts a %laplace_distribution random number distribution
     302              :  * @p __x from the input stream @p __is.
     303              :  *
     304              :  * @param __is An input stream.
     305              :  * @param __x A %laplace_distribution random number
     306              :  *            generator engine.
     307              :  *
     308              :  * @returns The input stream with @p __x extracted or in an error state.
     309              :  */
     310              : template <typename _RealType, typename _CharT, typename _Traits>
     311              : std::basic_istream<_CharT, _Traits> &operator>>( std::basic_istream<_CharT, _Traits> &,
     312              :                                                  laplace_distribution<_RealType> & );
     313              : 
     314              : /** \ingroup random
     315              :  * @{
     316              :  */
     317              : 
     318              : /// Alias for a uniform random variate
     319              : template <typename realT>
     320              : using uniDistT = randomT<realT, std::mt19937_64, std::uniform_real_distribution<realT>>;
     321              : 
     322              : /// Alias for a standard normal random variate
     323              : template <typename realT>
     324              : using normDistT = randomT<realT, std::mt19937_64, std::normal_distribution<realT>>;
     325              : 
     326              : /// Alias for an exponential random variate
     327              : template <typename realT>
     328              : using expDistT = randomT<realT, std::mt19937_64, std::exponential_distribution<realT>>;
     329              : 
     330              : /// Alias for a laplace random variate
     331              : template <typename realT>
     332              : using lapDistT = randomT<realT, std::mt19937_64, laplace_distribution<realT>>;
     333              : 
     334              : /// Alias for a poisson random variate
     335              : template <typename intT>
     336              : using poissonDistT = randomT<intT, std::mt19937_64, std::poisson_distribution<intT>>;
     337              : 
     338              : /// Alias for a log normal variate
     339              : template <typename realT>
     340              : using lognormDistT = randomT<realT, std::mt19937_64, std::lognormal_distribution<realT>>;
     341              : 
     342              : /// @}
     343              : 
     344              : } // namespace math
     345              : } // namespace mx
     346              : 
     347              : #endif // mx_math_randomT_hpp
     348              : 
     349              : /*5/22/06: added 64 bit mersenne twister support
     350              :  */
        

Generated by: LCOV version 2.0-1