/* * Generate a uniform distribution on the half-open interval [lower, upper). */ double rds_uniform( mt_state * state, /* State of the MT PRNG to use */ double lower, /* Lower limit of distribution */ double upper) /* Upper limit of distribution */ { return lower + mts_drand(state) * (upper - lower); }
/* * Generate a p-Erlang distribution with the given mean. */ double rds_erlang( mt_state * state, /* State of the MT PRNG to use */ int p, /* Order of distribution to generate */ double mean) /* Mean of generated distribution */ { int order; /* Order generated so far */ double random_value; /* Value generated so far */ do { if (p <= 1) p = 1; random_value = mts_drand(state); for (order = 1; order < p; order++) random_value *= mts_drand(state); } while (random_value == 0.0); return -mean * log(random_value) / p; }
/* * Generate an exponential distribution with the given mean. */ double rds_exponential( mt_state * state, /* State of the MT PRNG to use */ double mean) /* Mean of generated distribution */ { double random_value; /* Random sample on [0,1) */ do random_value = mts_drand(state); while (random_value == 0.0); return -mean * log(random_value); }
/* * Generate a Weibull distribution with the given shape and scale parameters. */ double rds_weibull( mt_state * state, /* State of the MT PRNG to use */ double shape, /* Shape of the distribution */ double scale) /* Scale of the distribution */ { double random_value; /* Random sample on [0,1) */ do random_value = mts_drand(state); while (random_value == 0.0); return scale * exp(log(-log(random_value)) / shape); }
/* * Generate a normal distribution with the given mean and standard * deviation. See Law and Kelton, p. 491. */ double rds_normal( mt_state * state, /* State of the MT PRNG to use */ double mean, /* Mean of generated distribution */ double sigma) /* Standard deviation to generate */ { double mag; /* Magnitude of (x,y) point */ double offset; /* Unscaled offset from mean */ double xranval; /* First random value on [-1,1) */ double yranval; /* Second random value on [-1,1) */ /* * Generating a normal distribution is a bit tricky. We may need * to make several attempts before we get a valid result. When we * are done, we will have two normally distributed values, one of * which we discard. */ do { xranval = 2.0 * mts_drand(state) - 1.0; yranval = 2.0 * mts_drand(state) - 1.0; mag = xranval * xranval + yranval * yranval; } while (mag > 1.0 || mag == 0.0); offset = sqrt((-2.0 * log(mag)) / mag); return mean + sigma * xranval * offset; /* * The second random variate is given by: * * mean + sigma * yranval * offset; * * If this were a C++ function, it could probably save that value * somewhere and return it in the next subsequent call. But * that's too hard to make bulletproof (and reentrant) in C. */ }
/* * Generate a triangular distibution between given limits, with a * given mode. */ double rds_triangular( mt_state * state, /* State of the MT PRNG to use */ double lower, /* Lower limit of distribution */ double upper, /* Upper limit of distribution */ double mode) /* Highest point of distribution */ { double ran_value; /* Value generated by PRNG */ double scaled_mode; /* Scaled version of mode */ scaled_mode = (mode - lower) / (upper - lower); ran_value = mts_drand(state); if (ran_value <= scaled_mode) ran_value = sqrt(scaled_mode * ran_value); else ran_value = 1.0 - sqrt((1.0 - scaled_mode) * (1.0 - ran_value)); return lower + (upper - lower) * ran_value; }
inline float urand(Sampler *s) { return mts_drand(&s->mState); }
real_t Sampler::urand(real_t lower, real_t upper) { return mts_drand(&m_state) * (upper-lower)+lower; //rds_uniform(&m_state, lower, upper); }