star-sp

Random number generators and distributions
git clone git://git.meso-star.fr/star-sp.git
Log | Files | Refs | README | LICENSE

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