Trail: MersenneTwister

Performance Testing : MersenneTwister

KnowledgeBase :: Categories :: PageIndex :: RecentChanges :: RecentlyCommented :: Login/Register

Custom VuC Functions: Mersenne Twister-based Random functions

Originally written for IBM Rational DeveloperWorks

The Mersenne Twister Random generator based functions generate pseudo random integers of a better randomness than the built-in random functions. The functions contained in this code are alternatives for the VuC rand and uniform functions.

The standard VuC rand, srand and uniform functions are at the basis of VuC randomizer functions. The algorithm that is used to generate the random numbers creates less than perfect random results under certain circumstances. Research by Calvin Arnason, the user who made the observation about the random functions on the Performance and VU Testing forum, yielded an alternative. This alternative is officially called "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number Generator". This random number generator was originally conceived by Makoto Matsumoto and Takuji Nishimura of Keio University, Yokohama, Japan. The homepage for this generator can be found at

Since the code is made available publicly under the GNU license and BSD license, an attempt was made to make this generator work in VuC. After solving several issues with the code, we now have a working MT random number generator with a very high quality random number output.

There are no external requirements to use this function.

Function Code
There are actually 3 active functions included in the code below.

mtrand: This function will retrieve a random number between 0 and 32767. This is an alternative to the VuC rand function.
smtrand: The function that is used to "seed" the randomizer. Seeding is mandatory and the default seed is 4357.
mtuniform: This function will retrieve a random number in a specified range. This is an alternative to the VuC uniform function.

/* A C-program for MT19937: Integer version (1999/10/28) */
/* genrand() generates one pseudorandom unsigned integer (32bit) */
/* which is uniformly distributed among 0 to 2^32-1 for each */
/* call. sgenrand(seed) sets initial values to the working area */
/* of 624 words. Before genrand(), sgenrand(seed) must be */
/* called once. (seed is any 32-bit integer.) */
/* Coded by Takuji Nishimura, considering the suggestions by */
/* Topher Cooper and Marc Rieffel in July-Aug. 1997. */
/* Adapted for use in Rational VuC by Roland Stens after a */
/* suggestion by Calvin Arnason. */
/* Feedback on this implementation can be sent to */
/* */
/* This library is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Library General Public */
/* License as published by the Free Software Foundation; either */
/* version 2 of the License, or (at your option) any later */
/* version. */
/* This library is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* See the GNU Library General Public License for more details. */
/* You should have received a copy of the GNU Library General */
/* Public License along with this library; if not, write to the */
/* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */
/* 02111-1307 USA */
/* Copyright (C) 1997, 1999 Makoto Matsumoto and Takuji Nishimura. */
/* Any feedback is very welcome. For any question, comments, */
/* see or email */
/* */
/* M. Matsumoto and T. Nishimura, */
/* "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform */
/* Pseudo-Random Number Generator", */
/* ACM Transactions on Modeling and Computer Simulation, */
/* Vol. 8, No. 1, January 1998, pp 3--30. */

#include <VU.h>

/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0df /* constant vector a */
#define UPPER_MASK 0x80000000 /* most significant w-r bits */
#define LOWER_MASK 0x7fffffff /* least significant r bits */

/* Tempering parameters */
#define TEMPERING_MASK_B 0x9d2c5680
#define TEMPERING_MASK_C 0xefc60000
#define TEMPERING_SHIFT_U(y) (y >> 11)
#define TEMPERING_SHIFT_S(y) (y << 7)
#define TEMPERING_SHIFT_T(y) (y << 15)
#define TEMPERING_SHIFT_L(y) (y >> 18)

int mt[N]; /* the array for the state vector */
int mti; /* mti==N+1 means mt[N] is not initialized */

/* Initializing the array with a seed */
proc sgenrand(seed)
int seed;
int i;
    for (i=0;i<N;i++) {
    mt[i] = seed & 0xffff0000;
    seed = 69069 * seed + 1;
    mt[i] |= (seed & 0xffff0000) >> 16;
    seed = 69069 * seed + 1;
mti = N;

/* Initialization by "sgenrand()" is an example. Theoretically, */
/* there are 2^19937-1 possible states as an intial state. */
/* This function allows to choose any of 2^19937-1 ones. */
/* Essential bits in "seed_array[]" is following 19937 bits: */
/* (seed_array[0]&UPPER_MASK), seed_array[1], ..., seed_array[N-1]. */
/* (seed_array[0]&LOWER_MASK) is discarded. */
/* Theoretically, */
/* (seed_array[0]&UPPER_MASK), seed_array[1], ..., seed_array[N-1] */
/* can take any values except all zeros. */

proc lsgenrand(seed_array)
int seed_array[];
/* the length of seed_array[] must be at least N */
    for (i=0;i<N;i++)
    mt[i] = seed_array[i];

int func genrand()
    int y;
int mag01[2]={0x0, MATRIX_A};
/* mag01[x] = x * MATRIX_A for x=0,1 */

if (mti >= N) { /* generate N words at one time */
int kk;

if (mti == N+1) /* if sgenrand() has not been called, */
sgenrand(4357); /* a default initial seed is used */

for (kk=0;kk<N-M;kk++) {
    y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
    mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];

for (;kk<N-1;kk++) {
    y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
    mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];

y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
mti = 0;

y = mt[mti++];
return y;

/* "Mersenne Twister" VuC Random functions added Roland Stens */
/* Replacement for the "uniform" function */
    int func mtuniform(start,end)
    int start;
    int end;
return abs(genrand() % (end-start+1)) + start;

/* Replacement for the "rand" function */
int func mtrand()
    return abs(genrand() % 32768);

/* Replacement for the "srand" function */
proc smtrand(seed)
int seed;

This code can be placed in each calling script immediately following the #include command, or it can go in a separate .h file referenced by an additional #include command. Theses functions can then be put in either the test script section of the repository or the Rational Test include directory. Putting it in the latter location will give you the benefit of not having to copy this function into every repository you work with.

Command Syntax

int mtuniform (min_value, max_value)

Syntax Element Description
min_value An integer expression whose value generally specifies the minimum random integer to be returned.
max_value An integer expression whose value generally specifies the maximum random integer to be returned.

The mtuniform routine returns a random integer uniformly distributed in the specified range. The function is an alternative for the VuC uniform function.

int mtrand ()

The mtrand routine returns a random integer uniformly distributed between 0 and Returns a random integer in the range 0 to 32767. The function is an alternative for the VuC rand function.

smtrand (seed)

Syntax Element Description
seed The integer expression used to seed the random number generator. Its value must be non-negative.
The smtrand function seeds the random generator. Seeding is mandatory and the default seed is 4357. This function differs from the VuC srand function, because it does not return a value.

Examples of Use
To use this random number generator, first include this function script at the top of your VU Script or make the function script into a .h file and include it directly after the "vu.h" line.

#include "mtrandom.h"

Try the functions with the following example. This will create 500 random numbers from 1 to 1000.
for (i=0; i<500; i++)
    printf("%dn", mtuniform(1,1000));

This can be used, for instance, to spread the start of a large group of Virtual Users. If the requirement is that every user at least has to wait 2 seconds but has to proceed after a maximum of 30 seconds, you can implement the following code:

smtrand(_uid * 100);

/* Set Delay Time for each user to start at different random time */

delay(mtuniform(_uid * 2000,_uid * 30000));

/* End Set Delay Time */

About the Author

Roland Stens is an independent QA and Testing specialist based in Vancouver, BC Canada.

Roland is a senior consultant specializing in testing and in particularly in performance and robustness testing. His background is in programming, system analysis, database and network management, testing and project/test management. As an active participant on various Performance Testing related forums he shares his insights with other users to help expand their knowledge and vision of the tools and testing processes. He's happy to answer questions by e-mail.

There are no comments on this page. [Add comment]

Page History :: 2007-10-01 16:43:48 XML :: Owner: Admin :: Search:
Valid XHTML 1.0 Transitional :: Valid CSS :: Powered by Wikka Wakka Wiki
Page was generated in 0.0546 seconds