PseudoRandomNumberGeneratorV2
This module is another implementation of the PseudoRandomNumberGenerator by David Eather.
Instead of the multiple files and module references used in the original, it's a single module for all data types, with the desired output set via '#option RAND_T'.
It supports data types byte, word, longword, or float, and adds a new overloaded function GetRND(lower, upper) that returns a random number within the range (lower, upper)
See the original wiki page for details on the random number generation algorithm.
Usage
Set the desired random number datatype using '#option RAND_T' and include the file rand.bas. That's it.
Here's an example for a random byte (the default)
// select random number type... supports byte, word, longword, or float #option RAND_T = byte include "rand.bas" dim Y as RAND_T ' Y is a byte in this example rand.InitializeRND(123) ' set new seed (optional) while (true) Y = GetRND() ' get a random number 0-255 (byte value, as set by RAND_T) Y = rand.GetRND(1, 5) ' get a random byte in the range of 1 to 5 end while
To get different random number types, simply change '#option RAND_T = ' to match the data type you want... ie '#option RAND_T = word' or '#option RAND_T = float'
Rand.bas Module
This is the module code for the above example. Just copy and paste into the Swordfish IDE and save in your UserLibrary folder as "rand.bas"
{ ***************************************************************************** * Name : rand.bas * * Author : David Eather (modified by Jerry Messina) * * Notice : This code is placed into the Public Domain * * Date : 11 APR 2023 * * Version : 1.1 11 APR 2023 JM * * : - based on v1.0 code by David Eather * * : - unify code to single file * * : - set GetRND() return value type using '#option RAND_T' * * : - add longword support * * : - add overloaded GetRND function to get number in a range * * : GetRND(lower as RAND_T, upper as RAND_T) as RAND_T * * : 1.0 19/07/2011 * * : - original version by David Eather * ***************************************************************************** } module rand // select GetRND() random number data type - byte, word, longword, or float #option RAND_T = byte #if not(RAND_T in (byte, word, longword, float)) #error RAND_T, "RAND_T type not supported" #endif #if (RAND_T = byte) type RAND_T = byte type RAND_RESEED_T = byte dim GLFSR as byte = 1 dim LCG as byte = 84 const LCG_MASK as byte = $FF const GLFSR_TAP as byte = 135 const GLFSR_OR as byte = $80 #elseif (RAND_T = word) type RAND_T = word type RAND_RESEED_T = word dim GLFSR as word = 1 dim LCG as word = 21844 const LCG_MASK as word = $FFFF const GLFSR_TAP as word = 447 const GLFSR_OR as word = $8000 #elseif (RAND_T = longword) type RAND_T = longword type RAND_RESEED_T = longword dim GLFSR as longword = 1 dim LCG as longword = 5592404 const LCG_MASK as longword = $FFFFFFFF const GLFSR_TAP as longword = 7679 const GLFSR_OR as longword = $80000000 #elseif (RAND_T = float) type RAND_T = float type RAND_RESEED_T = longword dim GLFSR as longword = 1 // only 24-bits are used (mantissa) dim LCG as longword = 5592404 const LCG_MASK as longword = $00FFFFFF // limit value to 16777215 const GLFSR_TAP as longword = 7679 const GLFSR_OR as longword = $01000000 #endif // get a random number // return value based on option RAND_T: // byte = 0 to 255 // word = 0 to 65535 // longword = 0 to 4294967295 // float = 0.0 to 0.9999999 public function GetRND() as RAND_T // LCG #if (RAND_T = byte) LCG = byte(LCG * 7) + 17 #elseif (RAND_T = word) LCG = word(LCG * 127) + 259 #elseif (RAND_T = longword) LCG = (LCG * 2047 + 4091) #elseif (RAND_T = float) LCG = (LCG * 2047 + 4091) and LCG_MASK #endif // Galios LFSR if (GLFSR.bits(0) = 1) Then GLFSR = GLFSR xor GLFSR_TAP GLFSR = (GLFSR >> 1) or GLFSR_OR else GLFSR = (GLFSR >> 1) endif #if (RAND_T = float) result = (LCG xor GLFSR) and $7FFFFF // limit float value to 0.999999 result = result / $800000 #else result = (LCG xor GLFSR) #endif end function // get a random number in the range (lower, upper) // overload public function GetRND(lower as RAND_T, upper as RAND_T) as RAND_T #if (RAND_T = float) dim f, range as float f = GetRND() // 0 - 0.9999 range = upper - lower result = (f * range) + lower #else result = (GetRND() mod (upper - lower + 1)) + lower #endif end function // reseed the random number generator public sub InitializeRND(reseed as RAND_RESEED_T) LCG = reseed and LCG_MASK // make the start values very different - not really important // except that GLFSR must not be zero GLFSR = LCG xor ($55555555 and LCG_MASK) if (GLFSR = 0) then GLFSR = 1 endif end sub end module