Branch data Line data Source code
1 : : // ***************************************************************************** 2 : : /*! 3 : : \file src/RNGTest/StatTest.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 statistical test 9 : : \details This file defines a generic random number generator statistical 10 : : test class. The class uses runtime polymorphism without client-side 11 : : inheritance: inheritance is confined to the internals of the class, 12 : : invisible to client-code. The class exclusively deals with ownership 13 : : enabling client-side value semantics. Credit goes to Sean Parent at Adobe: 14 : : https://github.com/sean-parent/ 15 : : sean-parent.github.com/wiki/Papers-and-Presentations. 16 : : */ 17 : : // ***************************************************************************** 18 : : #ifndef StatTest_h 19 : : #define StatTest_h 20 : : 21 : : #include <functional> 22 : : #include <memory> 23 : : 24 : : #include "NoWarning/charm++.hpp" 25 : : 26 : : #include "Macro.hpp" 27 : : #include "Options/RNG.hpp" 28 : : 29 : : namespace rngtest { 30 : : 31 : : //! \brief Random number generator statistical test 32 : : //! \details This class uses runtime polymorphism without client-side 33 : : //! inheritance: inheritance is confined to the internals of the this class, 34 : : //! invisible to client-code. The class exclusively deals with ownership 35 : : //! enabling client-side value semantics. Credit goes to Sean Parent at Adobe: 36 : : //! https://github.com/sean-parent/sean-parent.github.com/wiki/ 37 : : //! Papers-and-Presentations. For example client code that models a Battery, 38 : : //! see rngtest::TestU01. 39 : : class StatTest { 40 : : 41 : : public: 42 : : //! \brief Constructor taking a function pointer to a constructor of an 43 : : //! object modeling Concept 44 : : //! \details Passing std::function allows late execution of the constructor 45 : : //! of T, i.e., at some future time, and thus usage from a factory. Note 46 : : //! that the value of the first function argument, std::function<T()>, is 47 : : //! not used here, but its constructor type, T, is used to enable the 48 : : //! compiler to deduce the model constructor type, used to create its 49 : : //! Charm proxy, defined by T::Proxy. The actual constructor of T is not 50 : : //! called here but at some future time by the Charm++ runtime system, 51 : : //! here only an asynchrounous ckNew() is called, i.e., a message (or 52 : : //! request) for a future call to T's constructor. This overload can only 53 : : //! be used for Charm++ chare objects defining typedef 'Proxy', which must 54 : : //! define the Charm++ proxy. All optional constructor arguments are 55 : : //! forwarded to ckNew() and thus to T's constructor. If it was somehow 56 : : //! possible to obtain all bound arguments' types and values from an 57 : : //! already-bound std::function, we could use those instead of having to 58 : : //! explicitly forward the model constructor arguments via this host 59 : : //! constructor. 60 : : //! \param[in] c Function pointer to a constructor of an object modeling 61 : : //! Concept 62 : : //! \param[in] args Constructor arguments 63 : : //! \see See also tk::recordCharmModel(). 64 : : template< typename T, typename... CtrArgs > 65 : 120 : explicit StatTest( std::function<T()> c [[maybe_unused]], CtrArgs... args ) 66 : : : self( std::make_unique< Model< typename T::Proxy > > 67 [ + - ]: 120 : (std::move(T::Proxy::ckNew(std::forward<CtrArgs>(args)...))) ) { 68 [ - + ][ - - ]: 120 : Assert( c == nullptr, "std::function argument to StatTest Charm " [ - - ][ - - ] 69 : : "constructor must be nullptr" ); 70 : 120 : } 71 : : 72 : : //! Public interface to contribute number of results/test, i.e., p-values 73 : 40 : void npval() const { self->npval(); } 74 : : 75 : : //! Public interface to contribute test name(s) 76 : 40 : void names() const { self->names(); } 77 : : 78 : : //! Public interface to running a test 79 : 120 : void run() const { self->run(); } 80 : : 81 : : //! Public interface to contributing a test's run time measured in seconds 82 : 120 : void time() const { self->time(); } 83 : : 84 : : //! Copy assignment 85 : : StatTest& operator=( const StatTest& x ) 86 : : { StatTest tmp(x); *this = std::move(tmp); return *this; } 87 : : //! Copy constructor 88 : : StatTest( const StatTest& x ) : self( x.self->copy() ) {} 89 : : //! Move assignment 90 : : StatTest& operator=( StatTest&& ) noexcept = default; 91 : : //! Move constructor 92 : 276 : StatTest( StatTest&& ) 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 : 120 : Concept() = default; 99 : 0 : Concept( const Concept& ) = default; 100 : 0 : virtual ~Concept() = default; 101 : : virtual Concept* copy() const = 0; 102 : : virtual void npval() = 0; 103 : : virtual void names() = 0; 104 : : virtual void run() = 0; 105 : : virtual void time() = 0; 106 : : }; 107 : : 108 : : //! Model models the Concept above by deriving from it and overriding the 109 : : //! the virtual functions required by Concept 110 : : template< typename T > 111 : : struct Model : Concept { 112 [ + - ]: 120 : explicit Model( T x ) : data( std::move(x) ) {} 113 [ - - ]: 0 : Concept* copy() const override { return new Model( *this ); } 114 : 40 : void npval() override { data.npval(); } 115 : 40 : void names() override { data.names(); } 116 : 120 : void run() override { data.run(); } 117 : 120 : void time() override { data.time(); } 118 : : T data; 119 : : }; 120 : : 121 : : std::unique_ptr< Concept > self; //!< Base pointer used polymorphically 122 : : }; 123 : : 124 : : } // rngtest:: 125 : : 126 : : #endif // StatTest_h