Mersenne Twister for Visual Basic .NET

Home (Get Mersenne Twister for Visual Basic 2012, 2010, 2008 and 2005 there.)

Overview

Mersenne Twister (MT) is a long period, fast, high quality pseudo-random number generator (PRNG). Its period is 219937-1 (approximately 106002). It has equidistribution in 623 dimensions. The Visual Basic .NET class MTRandom implementing Mersenne Twister (in mt19937ar.vb) produces over 60 million 32-bit pseudo-random integers per second on a 2.66 GHz Intel Core2 Duo processor. MT has a sound theoretical basis and has been tested thoroughly. The original MT authors' site has details about the algorithm and MT for other programming languages.

MTRandom has functions to produce 32-, 64- and 128-bit integers, as well as 32- and 53-bit precision reals. In all, MTRandom provides sixteen equidistribution generator functions and six initializing methods. Saving a generator's state to a file and loading it later is simple.

MTRandom has been successfully tested against the original MT authors' mt19937ar.c code by generating 100 million integers and 100 million reals with both, and comparing the entire outputs.

MTRandom passes George Marsalia's Diehard tests.

MTRandom implements MT as a VB class. Code is included in a separate file to demonstrate use of the VB class in your program. Test code for the class is also included to duplicate the original authors' mt19937ar.out file.

MTRandom will not compile with VB 6 or earlier.

This MTRandom (mt19937ar.vb) release is version 4.1, dated 2012-08-19, and contains the following changes:

VB files in this package

FILE                        CONTENTS
------------------------    ---------------------------------------------------
mt19937ar.vb                The only file necessary to use the PRNGs.  It
                            consists of one Visual Basic .NET PRNG class:
                            MTRandom; and some exception classes used by
                            MTRandom.

Main.vb                     The original MT authors' test duplicated in VB .NET;
                            it also calls the following modules:

MakeEntropyTestData.vb      Makes a file to test with John Walker's 'ent.exe'
                            entropy and chi-squared program available at
                            http://www.fourmilab.ch/random/

MakeDiehardData.vb          Makes a file to test with George Marsaglia's
                            Diehard tests

Demo.vb                     Demonstrates how to initialize and use the PRNGs

SimplePerformanceTest.vb    The simple performance test described in mt19937ar.vb

MersenneTwister.vbproj      VB Project file for Visual Basic 2010.  It likely
                            won't work with Visual Basic 2008 or 2005.  For
                            VB 2008 and 2005 make an empty console project
                            and add to it the *.vb files named above.

Excerpts* from file mt19937ar.vb

' mt19937ar.vb version 4.1 (for Visual Basic .NET), 2012-08-19, by Ron Charlton:
'
' This file implements the Mersenne Twister (MT), MT19937ar,
' pseudo-random number generator (PRNG) as a Visual Basic .NET
' class.
'
' To use Mersenne Twister:
'   1) Add this file (only) to your VB project
'   2) For VB 2010 or later, add a project reference to BigInteger by
'     selecting Visual Basic 2010 menu item
'          Project/AddReference.../.NET/System.Numerics
'   3) By default mt19937ar.vb has a genrand_int128SignedInt() function,
'      and requires VB 2010 or later for data type BigInteger.
'      Leave uncommented only one of the these two #Const statements:
'
' Uncomment the next line (only) for Visual Basic 2010 and later:
#Const VB2010orLater = True
'
' Uncomment the next line (only) for Visual Basic 2008 and 2005:
'#Const VB2010orLater = False
'
' (Also change the #Const in Demo.vb if you include it in your
' VB2008/VB2005 project.)
'
' NOTE: genrand_int128SignedInt() takes about 19 times as long
' to run as genrand_int64().  Data type BigInteger is SLOW on
' 32 and 64 bit Windows!

'/*

'   A C-program for MT19937, with initialization improved 2002/1/26.
'   Coded by Takuji Nishimura and Makoto Matsumoto.
'
'   Before using, initialize the state by using init_genrand(seed)
'   or init_by_array(init_key, key_length).
'
'   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
'   All rights reserved.
'
'   Redistribution and use in source and binary forms, with or without
'   modification, are permitted provided that the following conditions
'   are met:
'
'     1. Redistributions of source code must retain the above copyright
'        notice, this list of conditions and the following disclaimer.
'
'     2. Redistributions in binary form must reproduce the above copyright
'        notice, this list of conditions and the following disclaimer in the
'        documentation and/or other materials provided with the distribution.
'
'     3. The names of its contributors may not be used to endorse or promote
'        products derived from this software without specific prior written
'        permission.
'
'   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
'   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
'   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
'   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
'   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
'   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
'   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
'   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
'   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
'   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
'   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'
'
'   Any feedback is very welcome.
'   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
'   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
'*/

FUNCTIONS AND PROCEDURES IMPLEMENTED:
'
'       Function                    Returns values in the range:
'       -------------------------   -------------------------------------------------------
'       genrand_int32()             [0, 4294967295]  (0 to 2^32-1)
'
'       genrand_int31()             [0, 2147483647]  (0 to 2^31-1)
'
'       genrand_real1()             [0.0, 1.0]   (both 0.0 and 1.0 included)
'
'       genrand_real2()             [0.0, 1.0) = [0.0, 0.9999999997672...]
'                                                (0.0 included, 1.0 excluded)
'
'       genrand_real3()             (0.0, 1.0) = [0.0000000001164..., 0.9999999998836...]
'                                                (both 0.0 and 1.0 excluded)
'
'       genrand_res53()             [0.0,~1.0] = [0.0, 1.00000000721774...]
'                                                (0.0 included, ~1.0 included)
'
'       The following ADDITIONAL functions
'       ARE NOT PRESENT IN THE ORIGINAL C CODE:
'
'       NOTE: the limits shown below, marked with (*), are valid if gap==5.0e-13
'
'       genrand_int32SignedInt()   [-2147483648, 2147483647]   (-2^31 to 2^31-1)
'
'       genrand_real2b()           [0.0, 1.0)=[0, 1-(2*gap)] =[0.0, 0.9999999999990] (*)
'                                             (0.0 included, 1.0 excluded)
'
'       genrand_real2c()           (0.0, 1.0]=[0+(2*gap),1.0]=[1.0e-12, 1.0] (*)
'                                             (0.0 excluded, 1.0 included)
'
'       genrand_real3b()           (0.0, 1.0)=[0+gap, 1-gap] =[5.0e-13, 0.9999999999995] (*)
'                                             (both 0.0 and 1.0 excluded)
'
'
'       (See the "Acknowledgements" section for the following functions)
'
'       genrand_real4b()           [-1.0,1.0]=[-1.0, 1.0]
'                                             (-1.0 included, 1.0 included)
'
'       genrand_real5b()           (-1.0,1.0)=[-1.0+(2*gap), 1.0-(2*gap)]=
'                                                    [-0.9999999999990,0.9999999999990] (*)
'                                             (-1.0 excluded, 1.0 excluded)
'
'       genrand_intMax(upper)           [0,upper] for upper < 2^32  (0 to 4294967295 but <= upper)
'
'       genrand_intRange(lower,upper)   [lower,upper] for 0 <= lower <= upper <= 2^32-1
'                                                   (0 <= lower <= upper <= 4294967295)
'
'       genrand_int64()                 [0,18446744073709551615]    (0 to 2^64-1)
'
'       genrand_int128SignedInt()       [-2^127,2^127-1]
'                                                   (-170141183460469231731687303715884105728 to
'                                                      170141183460469231731687303715884105727)
'
'       Procedure                 Arguments
'       ------------------------  ---------------------------------------------------------
'       init_genrand(seed)        any seed included in [0,4294967295]
'       init_by_array(array)      array has elements of type UInteger;
'                                 the array must have at least one element
'
'       [Visual Basic .NET]
'       init_random(True|False)   True:  reseed VB Random from the system clock,
'                                        then reseed MTRandom from VB Random
'                                 False: use the next value from VB Random to
'                                        reseed MTRandom
'       init_by_crypto(0.0)       0.0 (cryptographically randomize the
'                                 PRNG state; this DOES NOT make mt19937ar
'                                 cryptographically secure, it provides the
'                                 full range of possible initialized states/
'                                 sequences).  Changing the argument value
'                                 (not its type) will not affect initialization
'       saveState(fileName)       any valid file name
'       loadState(fileName)       name of any file saved earlier with saveState()

- USAGE:
'
' In your Visual Basic .NET application:
'
'   1) Add this file to your Visual Basic .NET project, and add a project
'      reference to BigInteger with menu item
'          Project/AddReference/.NET/System.Numerics.
'
'   2) Create one or more instances of the MTRandom class.  The pseudo-random
'      sequence for each instance is initialized based on the arguments.
'      Make certain each instance stays in scope for the duration of its use so
'      it won't be re-initialized inadvertently.  Six different methods of
'      initialization are:
'
'           a) Dim r As New MTRandom()
'                   Initialize with seed == 5489 (the original MT
'                   authors' default seed).
'
'           b) Dim r As New MTRandom(19456)
'                   Initialize with seed==19456.  Any unsigned integer seed
'                   in the range [0,4294967295] is acceptable.
'
'           c) Dim init() As UInteger = {&H123, &H234, &H345, &H456}
'              Dim r As New MTRandom(init)
'                   Initialize with an array of unsigned integers (as in the
'                   original MT authors' version).  The array must have
'                   at least one element. 624 elements are desirable.  More
'                   or fewer elements are acceptable.  The element values
'                   should be random.
'
'           d) Dim r As New MTRandom(True)
'                   Seed VB Random from the system clock, and then
'                   seed MTRandom with the next value from VB Random.
'                   True is required but ignored.
'
'           e) Dim r As New MTRandom("filename.ext")
'                   Initialize with a generator state saved earlier with
'                   MTRandom.saveState("filename.ext")
'
'           f) Dim r As New MTRandom(0.0)
'                   Initialize with cryptographically random numbers from
'                   Visual Basic's RNGCryptoServiceProvider.  The argument
'                   0.0 is required but ignored.  Every new MTRandom instance
'                   that is initialized this way will have any one of
'                   approximately 2^19937 different beginning states.
'                   MTRandom WILL NOT BE MADE CRYPTOGRAPHICALLY SECURE
'                   BY THIS.
'
'   3) Call any of the genrand_X() functions listed above.  You can re-
'      initialize an MTRandom instance at any point by calling init_genrand(),
'      init_by_array(), init_random() or init_by_crypto().  You can save or
'      load the PRNG state at any point by calling saveState() or loadState().
'
'   4) Catch exceptions as desired.  The MTRandom exception classes are at the
'      end of this file.
'
' To test genrand_int32(), genrand_real2(), init_genrand() and init_by_array()
' in the Visual Basic .NET version of MT:
'
'   1) Create a Visual Basic .NET console application Project consisting of files
'           mt19937ar.vb
'           Demo.vb
'           SimplePerformanceTest.vb
'           MakeEntropyTestData.vb
'           MakeDiehardData.vb
'           Main.vb
'
'   2) Build and run the project.
'
'   3) Compare the file "mt19937arVBTest.out" with the original MT authors'
'      test output file ("mt19937ar.out", found by following
'      links at http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html).  
'      They should be identical.

ON PERFORMANCE:
'
'
'  SimplePerformanceTest.vb test results for MTRandom (Visual Basic .NET)
'
'   On a Dell Precision 390 workstation with 2.66 GHz Intel Core2 Duo processor,
'   3.5 GB RAM, Visual Basic .NET compiler, and generating 100,000,000 random numbers
'   with each function (running the Release version at a Cmd.exe prompt):
'
'                                   Seconds     Nanoseconds     Calls Per
'   Function                        Run Time    Per Call        Second
'   --------------------------      --------    -----------     ----------
'   genrand_int32()                  1.656        16.56         60,390,000
'   genrand_real1()                  2.031        20.31         49,240,000
'   genrand_res53()                  4.250        42.50         23,530,000
'   genrand_intMax(1000)             2.343        23.43         42,680,000
'   genrand_intMax(&H5FFFFFFF)       3.359        33.59         29,770,000
'   genrand_intRange(10,20)          3.813        38.13         26,230,000
'   genrand_int64()                  3.516        35.16         28,440,000
'   genrand_int128SignedInt()       65.695       656.95          1,522,177

*These Excerpts are from the header comments in file mt19937ar.vb. Please see the entire file header comments for further explanation of its development.

Contact

E-mail: Ron Charlton <Ron @ RonCharlton.org> (remove the spaces)
9002 Balcor Circle
Knoxville, TN 37923-2301 USA
Phone: 865-776-7345

Bug reports, improvements, corrections, complaints or kudos are welcomed.

Document last revised: 2024-08-17