Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/RNG/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
9 : : \details This file defines a generic random number generator class. The
10 : : class uses runtime polymorphism without client-side inheritance: inheritance
11 : : is confined to the internals of the class, invisible to client-code. The
12 : : class exclusively deals with ownership enabling client-side value semantics.
13 : : Credit goes to Sean Parent at Adobe: https://github.com/sean-parent/
14 : : sean-parent.github.com/wiki/Papers-and-Presentations.
15 : : */
16 : : // *****************************************************************************
17 : : #ifndef RNG_h
18 : : #define RNG_h
19 : :
20 : : #include <functional>
21 : : #include <memory>
22 : :
23 : : #include "Keywords.hpp"
24 : :
25 : : namespace tk {
26 : :
27 : : //! \brief Random number generator
28 : : //! \details This class uses runtime polymorphism without client-side
29 : : //! inheritance: inheritance is confined to the internals of the this class,
30 : : //! invisible to client-code. The class exclusively deals with ownership
31 : : //! enabling client-side value semantics. Credit goes to Sean Parent at Adobe:
32 : : //! https://github.com/sean-parent/sean-parent.github.com/wiki/
33 : : //! Papers-and-Presentations. For example client code that models a RNG, see
34 : : //! see tk::MKLRNG or tk::RNGSSE.
35 : : class RNG {
36 : :
37 : : using ncomp_t = kw::ncomp::info::expect::type;
38 : :
39 : : public:
40 : : //! \brief Constructor taking an object modeling Concept
41 : : //! \details The object of class T comes pre-constructed.
42 : : //! \param[in] x Instantiated object of type T given by the template
43 : : //! argument.
44 : : template< typename T >
45 : 1120 : explicit RNG( T x ) : self( std::make_unique< Model<T> >( std::move(x) ) ) {}
46 : :
47 : : //! \brief Constructor taking a function pointer to a constructor of an
48 : : //! object modeling Concept
49 : : //! \details Passing std::function allows late execution of the constructor,
50 : : //! i.e., as late as inside this class' constructor, and thus usage from a
51 : : //! factory.
52 : : //! \param[in] x Function pointer to a constructor of an object modeling
53 : : //! Concept
54 : : template< typename T >
55 : 361 : explicit RNG( std::function<T()> x ) :
56 [ + - ]: 361 : self( std::make_unique< Model<T> >( std::move(x()) ) ) {}
57 : :
58 : : //! Public interface to uniform RNG
59 : 2722911289 : void uniform( int stream, ncomp_t num, double* r ) const
60 : 2722911289 : { self->uniform( stream, num, r ); }
61 : :
62 : : //! Public interface to Gaussian RNG
63 : 1818204892 : void gaussian( int stream, ncomp_t num, double* r ) const
64 : 1818204892 : { self->gaussian( stream, num, r ); }
65 : :
66 : : //! Public interface to multi-variate Gaussian RNG
67 : 0 : void gaussianmv( int stream, ncomp_t num, ncomp_t d,
68 : : const double* const mean, const double* const cov,
69 : : double* r ) const
70 : 0 : { self->gaussianmv( stream, num, d, mean, cov, r ); }
71 : :
72 : : //! Public interface to beta RNG
73 : 1520112 : void beta( int stream, ncomp_t num, double p, double q, double a, double b,
74 : : double* r ) const
75 : 1520112 : { self->beta( stream, num, p, q, a, b, r ); }
76 : :
77 : : //! Public interface to gamma RNG
78 : 1620000 : void gamma( int stream, ncomp_t num, double a, double b, double* r ) const
79 : 1620000 : { self->gamma( stream, num, a, b, r ); }
80 : :
81 : : //! Public interface to number of threads accessor
82 : 154 : std::size_t nthreads() const noexcept { return self->nthreads(); }
83 : :
84 : : //! Copy assignment
85 : 14 : RNG& operator=( const RNG& x )
86 [ + - ]: 28 : { RNG tmp(x); *this = std::move(tmp); return *this; }
87 : : //! Copy constructor
88 : 70 : RNG( const RNG& x ) : self( x.self->copy() ) {}
89 : : //! Move assignment
90 : 14 : RNG& operator=( RNG&& ) noexcept = default;
91 : : //! Move constructor
92 : 1590 : RNG( RNG&& ) noexcept = default;
93 : :
94 : : private:
95 : : //! Concept is a pure virtual base class specifying the requirements of
96 : : //! polymorphic objects deriving from it
97 : : struct Concept {
98 : 1481 : Concept() = default;
99 : 70 : Concept( const Concept& ) = default;
100 : 1551 : virtual ~Concept() = default;
101 : : virtual Concept* copy() const = 0;
102 : : virtual void uniform( int, ncomp_t, double* ) const = 0;
103 : : virtual void gaussian( int, ncomp_t, double* ) const = 0;
104 : : virtual void gaussianmv( int, ncomp_t, ncomp_t, const double* const,
105 : : const double* const, double* ) const = 0;
106 : : virtual void beta(int, ncomp_t, double, double, double, double, double*)
107 : : const = 0;
108 : : virtual void gamma( int, ncomp_t, double, double, double* ) const = 0;
109 : : virtual std::size_t nthreads() const noexcept = 0;
110 : : };
111 : :
112 : : //! \brief Model models the Concept above by deriving from it and overriding
113 : : //! the virtual functions required by Concept
114 : : template< typename T >
115 : : struct Model : Concept {
116 [ + - ]: 1481 : explicit Model( T x ) : data( std::move(x) ) {}
117 [ + - ]: 70 : Concept* copy() const override { return new Model( *this ); }
118 : 2722911289 : void uniform( int stream, ncomp_t num, double* r ) const override
119 : 2722911289 : { data.uniform( stream, num, r ); }
120 : 1818204892 : void gaussian( int stream, ncomp_t num, double* r ) const override
121 : 1818204892 : { data.gaussian( stream, num, r ); }
122 : 0 : void gaussianmv( int stream, ncomp_t num, ncomp_t d,
123 : : const double* const mean, const double* const cov,
124 : : double* r ) const override
125 : 0 : { data.gaussianmv( stream, num, d, mean, cov, r ); }
126 : 1520112 : void beta( int stream, ncomp_t num, double p, double q, double a,
127 : : double b, double* r ) const override
128 : 1520112 : { data.beta( stream, num, p, q, a, b, r ); }
129 : 1620000 : void gamma( int stream, ncomp_t num, double a, double b, double* r ) const
130 : 1620000 : override { data.gamma( stream, num, a, b, r ); }
131 : 154 : std::size_t nthreads() const noexcept override { return data.nthreads(); }
132 : : T data;
133 : : };
134 : :
135 : : std::unique_ptr< Concept > self; //!< Base pointer used polymorphically
136 : : };
137 : :
138 : : } // namespace tk
139 : :
140 : : #endif // RNG_h
|