ssp_rng_c.h (5422B)
1 /* Copyright (C) 2015-2025 |Méso|Star> (contact@meso-star.com) 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #ifndef SSP_RNG_C_H 17 #define SSP_RNG_C_H 18 19 #include <rsys/rsys.h> 20 21 /* disable some warnings in Random123 includes */ 22 #ifdef COMPILER_GCC 23 #pragma GCC diagnostic push 24 #pragma GCC diagnostic ignored "-Wconversion" /* unsafe conversion */ 25 #pragma GCC diagnostic ignored "-Wshadow" 26 #pragma GCC diagnostic ignored "-Wunused-parameter" /* in Random123/aes.h */ 27 #elif defined(COMPILER_CL) 28 #pragma warning(push) 29 #pragma warning(disable:4100) /* unreferenced formal parameter */ 30 #pragma warning(disable:4127) /* conditional expression is constant */ 31 #pragma warning(disable:4512) /* assignment operator could not be generated */ 32 #pragma warning(disable:4521) /* multiple copy constructors specified */ 33 #endif 34 35 #include <Random123/conventional/Engine.hpp> 36 #include <Random123/threefry.h> 37 #ifdef WITH_R123_AES 38 #include <Random123/aes.h> 39 #endif 40 41 #ifdef COMPILER_GCC 42 #pragma GCC diagnostic pop 43 #elif defined(COMPILER_CL) 44 #pragma warning(pop) 45 #endif 46 47 #include "ssp.h" 48 #include <rsys/ref_count.h> 49 50 #define SQRT_2_PI 2.50662827463100050240 51 52 #ifdef USE_BOOST_RANDOM 53 /* Disable some warnings in boost includes */ 54 #pragma warning(push) 55 #pragma warning(disable:4244) /* possible loss of data due to data conversion */ 56 #pragma warning(disable:4458) /* declaration of a variable hides class member */ 57 58 /* The random C++11 library is bugged on MSVC 12 & 14. Use the boost version */ 59 #include <boost/random.hpp> 60 #include <boost/random/random_device.hpp> 61 #define RAN_NAMESPACE boost::random 62 63 #pragma warning(pop) 64 #pragma warning(push) 65 #pragma warning(disable:4706) /* Assignment in conditional expression */ 66 #else 67 #include <random> 68 #define RAN_NAMESPACE std 69 #endif 70 71 /* Generic Random Number Generator type descriptor */ 72 struct rng_desc { 73 res_T (*init)(struct mem_allocator* allocator, void* state); 74 void (*release)(void* state); 75 res_T (*set)(void* state, const uint64_t seed); 76 77 uint64_t (*get)(void* state); 78 res_T (*discard)(void* state, uint64_t n); 79 res_T (*read)(void* state, FILE* file); 80 res_T (*read_cstr)(void* state, const char* cstr); 81 res_T (*write)(const void* state, FILE* file); 82 res_T (*write_cstr)(const void* state, char* buf, const size_t sz, size_t* out_sz); 83 double (*entropy)(const void* state); 84 85 uint64_t min; 86 uint64_t max; 87 88 size_t sizeof_state; 89 size_t alignof_state; 90 }; 91 92 struct ssp_rng { 93 struct rng_desc desc; 94 enum ssp_rng_type type; 95 void* state; 96 struct mem_allocator* allocator; 97 98 /* Precomputed RNG constants used to speed up the canonical generations */ 99 long double r; /* max - min + 1 */ 100 size_t dbl_k; /* max(1, (#bits_mantisse_double + log2(r)) / log2(r)) */ 101 size_t flt_k; /* max(1, (#bits_mantisse_float + log2(r)) / log2(r)) */ 102 103 ref_T ref; 104 }; 105 106 /******************************************************************************* 107 * Local API 108 ******************************************************************************/ 109 extern LOCAL_SYM res_T 110 rng_create 111 (struct mem_allocator* allocator, 112 const struct rng_desc* desc, 113 struct ssp_rng** out_rng); 114 115 /******************************************************************************* 116 * C++ Wrappers 117 ******************************************************************************/ 118 template<typename ResultType, uint64_t Min, uint64_t Max> 119 class rng_cxx /* Wrap a SSP random generator into a CXX object */ 120 { 121 public: 122 FINLINE rng_cxx(struct ssp_rng& _rng) : rng(_rng) {} 123 FINLINE uint64_t operator()() { return rng.desc.get(rng.state); } 124 static constexpr uint64_t min() { return Min; } 125 static constexpr uint64_t max() { return Max; } 126 127 typedef ResultType result_type; 128 129 private: 130 struct ssp_rng& rng; 131 }; 132 133 template<typename Ran> typename Ran::result_type 134 wrap_ran(struct ssp_rng& rng, Ran& ran) 135 { 136 #define RNG_CXX(Type) rng_cxx<Type::result_type, Type::min(), Type::max()> 137 switch(rng.type) { 138 case SSP_RNG_KISS: { 139 class rng_cxx<uint64_t, 0, UINT32_MAX> rng_cxx(rng); 140 return ran(rng_cxx); 141 } 142 case SSP_RNG_MT19937_64: { 143 class RNG_CXX(RAN_NAMESPACE::mt19937_64) rng_cxx(rng); 144 return ran(rng_cxx); 145 } 146 case SSP_RNG_RANLUX48: { 147 class RNG_CXX(RAN_NAMESPACE::ranlux48) rng_cxx(rng); 148 return ran(rng_cxx); 149 } 150 case SSP_RNG_RANDOM_DEVICE: { 151 class RNG_CXX(RAN_NAMESPACE::random_device) rng_cxx(rng); 152 return ran(rng_cxx); 153 } 154 case SSP_RNG_THREEFRY: { 155 class RNG_CXX(r123::Engine<r123::Threefry4x64>) rng_cxx(rng); 156 return ran(rng_cxx); 157 } 158 #ifdef WITH_R123_AES 159 case SSP_RNG_AES: { 160 class RNG_CXX(r123::Engine<r123::AESNI4x32>) rng_cxx(rng); 161 return ran(rng_cxx); 162 } 163 #endif 164 default: FATAL("Unreachable code\n"); 165 } 166 #undef RNG_CXX 167 } 168 169 #endif /* SSP_RNG_C_H */ 170