random123

Counter-based Random Number Generators
git clone git://git.meso-star.com/random123.git
Log | Files | Refs | README | LICENSE

gsl_microrng.h (7114B)


      1 /*
      2 Copyright 2010-2011, D. E. Shaw Research.
      3 All rights reserved.
      4 
      5 Redistribution and use in source and binary forms, with or without
      6 modification, are permitted provided that the following conditions are
      7 met:
      8 
      9 * Redistributions of source code must retain the above copyright
     10   notice, this list of conditions, and the following disclaimer.
     11 
     12 * Redistributions in binary form must reproduce the above copyright
     13   notice, this list of conditions, and the following disclaimer in the
     14   documentation and/or other materials provided with the distribution.
     15 
     16 * Neither the name of D. E. Shaw Research nor the names of its
     17   contributors may be used to endorse or promote products derived from
     18   this software without specific prior written permission.
     19 
     20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     24 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31 */
     32 #ifndef __r123_gslmicrorng_dot_h__
     33 #define __r123_gslmicrorng_dot_h__
     34 
     35 
     36 #include <gsl/gsl_rng.h>
     37 #include <string.h>
     38 
     39 /**   The macro: GSL_MICRORNG(NAME, CBRNGNAME) is the GSL
     40    analog analog of the C++ r123::MicroURNG template.  It declares a gsl_rng
     41    type named gsl_rng_NAME which uses the underlying CBRNGNAME
     42    and can be invoked a limited number of times between calls to NAME_reset.
     43 
     44    When the underlying CBRNG's \c ctr_t is an \ref arrayNxW "r123arrayNxW",
     45    and the gsl_rng_NAME may called up to \c N*2^32 times 
     46    between calls to \c NAME_reset.
     47 
     48    \c NAME_reset takes a gsl_rng_NAME type, a counter and a key as arguments.
     49    It restarts the micro-rng with a new base counter and key.
     50 
     51    Note that you must call NAME_reset before the first use
     52    of a gsl_rng.  NAME_reset is not called automatically by
     53    gsl_rng_alloc().
     54 
     55    @code
     56    #include <Random123/threefry.h>
     57    #include <Random123/gsl_microrng.h> // this file
     58    GSL_MICRORNG(microcbrng, threefry4x64, 20)	// creates gsl_rng_microcbrng
     59 
     60    int main(int argc, char** argv) {
     61 	gsl_rng *r = gsl_rng_alloc(gsl_rng_microcbrng);
     62 	threefry4x64_ctr_t c = {{}};
     63 	threefry4x64_key_t k = {{}};
     64 
     65 	for (...) {
     66 	    c.v[0] = ??; //  some application variable
     67 	    microcbrng_reset(r, c, k);
     68 	    for (...) {
     69 		// gaussian calls r several times.  It is safe for
     70 		// r to be used upto 2^20 times in this loop
     71 		something[i] = gsl_ran_gaussian(r, 1.5);
     72 	    }
     73 	}
     74    }
     75    @endcode
     76    
     77 */
     78 
     79 #define GSL_MICRORNG(NAME, CBRNGNAME)                                   \
     80 const gsl_rng_type *gsl_rng_##NAME;                                     \
     81                                                                         \
     82 typedef struct{                                                         \
     83     CBRNGNAME##_ctr_t ctr;                                              \
     84     CBRNGNAME##_ctr_t r;                                                \
     85     CBRNGNAME##_key_t key;                                              \
     86     R123_ULONG_LONG n;                                                  \
     87     int elem;                                                           \
     88 } NAME##_state;                                                         \
     89                                                                         \
     90 static unsigned long int NAME##_get(void *vstate){                      \
     91     NAME##_state *st = (NAME##_state *)vstate;                          \
     92     const int N=sizeof(st->ctr.v)/sizeof(st->ctr.v[0]);                 \
     93     if( st->elem == 0 ){                                                \
     94         CBRNGNAME##_ctr_t c = st->ctr;                                  \
     95         c.v[N-1] |= st->n<<(R123_W(CBRNGNAME##_ctr_t)-32);              \
     96         st->n++;                                                        \
     97         st->r = CBRNGNAME(c, st->key);                                  \
     98         st->elem = N;                                                   \
     99     }                                                                   \
    100     return 0xffffffff & st->r.v[--st->elem];                            \
    101 }                                                                       \
    102                                                                         \
    103 static double                                                           \
    104 NAME##_get_double (void * vstate)                                       \
    105 {                                                                       \
    106     return NAME##_get (vstate)/4294967296.;                             \
    107 }                                                                       \
    108                                                                         \
    109 static void NAME##_set(void *vstate, unsigned long int s){              \
    110     NAME##_state *st = (NAME##_state *)vstate;                          \
    111     (void)s; /* ignored */                                              \
    112     st->elem = 0;                                                       \
    113     st->n = ~0; /* will abort if _reset is not called */                \
    114 }                                                                       \
    115                                                                         \
    116 static const gsl_rng_type NAME##_type = {                               \
    117     #NAME,                                                              \
    118     0xffffffffUL,                                                       \
    119     0,                                                                  \
    120     sizeof(NAME##_state),                                               \
    121     &NAME##_set,                                                        \
    122     &NAME##_get,                                                        \
    123     &NAME##_get_double                                                  \
    124 };                                                                      \
    125                                                                         \
    126 R123_STATIC_INLINE void NAME##_reset(const gsl_rng* gr, CBRNGNAME##_ctr_t c, CBRNGNAME##_key_t k) { \
    127     NAME##_state* state = (NAME##_state *)gr->state;                    \
    128     state->ctr = c;                                                     \
    129     state->key = k;                                                     \
    130     state->n = 0;                                                       \
    131     state->elem = 0;                                                    \
    132 }                                                                       \
    133                                                                         \
    134 const gsl_rng_type *gsl_rng_##NAME = &NAME##_type
    135 
    136 #endif