#include #include #include #include /* This is the NAG G05FAF generator. The generator returns the upper 32 bits from each term of the sequence, x_{n+1} = (a x_n) mod m using 59-bit unsigned arithmetic, with a = 13^{13} and m = 2^59. The seed specifies the upper 32 bits of the initial value, x_1, with the lower 16 bits set to 0x330E. The theoretical value of x_{10001} is 244131582646046. The period of this generator is ? FIXME (probably around 2^48). */ static inline void g05faf_advance (void *vstate); unsigned long int g05faf_get (void *vstate); double g05faf_get_double (void *vstate); void g05faf_set (void *state, unsigned long int s); static const unsigned short int a0 = 0xFD ; static const unsigned short int a1 = 0xC5 ; static const unsigned short int a2 = 0x23 ; static const unsigned short int a3 = 0x9B ; static const unsigned short int a4 = 0x76 ; static const unsigned short int a5 = 0x13 ; static const unsigned short int a6 = 0x01 ; static const unsigned short int a7 = 0x00 ; typedef struct { unsigned short int x0, x1, x2, x3, x4, x5, x6, x7 ; } g05faf_state_t; static inline void g05faf_advance (void *vstate) { g05faf_state_t *state = (g05faf_state_t *) vstate; const unsigned short int x0 = state->x0 ; const unsigned short int x1 = state->x1 ; const unsigned short int x2 = state->x2 ; const unsigned short int x3 = state->x3 ; const unsigned short int x4 = state->x4 ; const unsigned short int x5 = state->x5 ; const unsigned short int x6 = state->x6 ; const unsigned short int x7 = state->x7 ; unsigned long int a ; /* This looks like it will be pretty slow. Maybe someone can produce a more efficient implementation (it has to be portable though) */ a = a0 * x0 ; state->x0 = (a & 0x000000FFUL) ; a >>= 8 ; a += a0 * x1 + a1 * x0 ; state->x1 = (a & 0x000000FFUL) ; a >>= 8 ; a += a0 * x2 + a1 * x1 + a2 * x0 ; state->x2 = (a & 0x000000FFUL) ; a >>= 8 ; a += a0 * x3 + a1 * x2 + a2 * x1 + a3 * x0 ; state->x3 = (a & 0x000000FFUL) ; a >>= 8 ; a += a0 * x4 + a1 * x3 + a2 * x2 + a3 * x1 + a4 * x0 ; state->x4 = (a & 0x000000FFUL) ; a >>= 8 ; a += a0 * x5 + a1 * x4 + a2 * x3 + a3 * x2 + a4 * x1 + a5 * x0 ; state->x5 = (a & 0x000000FFUL) ; a >>= 8 ; a += a0 * x6 + a1 * x5 + a2 * x4 + a3 * x3 + a4 * x2 + a5 * x1 + a6 * x0 ; state->x6 = (a & 0x000000FFUL) ; a >>= 8 ; a += (a0 * x7 + a1 * x6 + a2 * x5 + a3 * x4 + a4 * x3 + a5 * x2 + a6 * x1 + a7 * x0) ; state->x7 = (a & 0x00000007UL) ; } unsigned long int g05faf_get (void *vstate) { g05faf_state_t *state = (g05faf_state_t *) vstate; g05faf_advance (state) ; return ((state->x7 << 29) + (state->x6 << 21) + (state->x5 << 13) + (state->x4 << 5) + (state->x3 >> 3)); } double g05faf_get_double (void * vstate) { g05faf_state_t *state = (g05faf_state_t *) vstate; g05faf_advance (state) ; return (ldexp((double) state->x7, -3) + ldexp((double) state->x6, -11) + ldexp((double) state->x5, -19) + ldexp((double) state->x4, -27) + ldexp((double) state->x3, -35) + ldexp((double) state->x2, -43) + ldexp((double) state->x1, -51) + ldexp((double) state->x0, -59)) ; } void g05faf_set (void *vstate, unsigned long int s) { g05faf_state_t *state = (g05faf_state_t *) vstate; if (s == 0) /* default seed */ s = 1 ; /* FIXME: I have no idea what the nag seeding procedure is */ return; } static const gsl_rng_type g05faf_type = {"g05faf", /* name */ 0xffffffffUL, /* RAND_MAX */ 0, /* RAND_MIN */ sizeof (g05faf_state_t), &g05faf_set, &g05faf_get, &g05faf_get_double }; const gsl_rng_type *gsl_rng_g05faf = &g05faf_type;