Pseudo-Random Number Generation
Algorithm creator(s)
Eddy Van Esch, Paul Dixon
PB author(s)
Eddy Van Esch
Description
Generates pseudo-random numbers that have a relative high degree of randomness.
Note
Numbers generated typically pass the ENT and DIEHARD tests.
Source
https://forum.powerbasic.com/forum/user-to-user-discussions/source-code/23994-randon-number-generators
See also
Source Code
Download source code file randomgen.bas (Right-click -> "Save as ...")
' RandomGenerator.bas -- Eddy Van Esch -- raimundo4u@yahoo.com
' Public domain. Use at your own risk.
' Code snippets used from Paul Dixon and PB Tech support.
'
' This program contains pseudo random number generator subs that generate
' pseudo random numbers that have a high degree of 'randomness'.
' This was the only criterium (randomness). I didn't check speed.
' I tested the output with randomness testing programs ENT and DIEHARD.
' These programs couldn't tell if the data were not real random numbers.
' So, the pseudo random numbers look pretty ... random...
'
' GetRandom1
' This random generator function is a combination of a pseudo random generator
' posted by Paul Dixon on the source forum and PB's standard RND() function.
'
' GetRandom2
' This random generator function is a combination of the CPU timestamp
' and PB's standard RND() function.
'
' To initialize the generators, just do the classical RANDOMIZE TIMER.
'
#COMPILE EXE
#DIM ALL
DECLARE FUNCTION GetRandom1() AS DWORD
DECLARE FUNCTION GetRandom2() AS DWORD
DECLARE FUNCTION HasRDTSC&
FUNCTION GetRandom1() AS DWORD
' Assembler code in this routine and next lines of comment by Paul Dixon.
'
' Fast PRBS generator. Produces maximal length
' 33 bit (2^33-1) sequence but only gives 32 new bits each time.
' rng is the 32 bit random number, set rng=seed to seed the
' number generator. Use RandomNumber???=rng to read the last
' generated number. Run the routine (inline for speed) to generate
' the next number. Uncomment the last line of the assembler code
' to also write the new number direct to the variable where it's
' needed.
' rng=1623 'this is the random number generator value. Presetting this
' 'variable can serve as seeding.
' rngh=1 'this is the 33rd bit of the random number generator
STATIC rng AS DWORD
STATIC rngh AS DWORD 'this is the 33rd bit of the random number generator
LOCAL k AS DWORD
LOCAL m AS DWORD
IF rng = 0 THEN rng = RND(0, 100000) 'This avoids having to define rng in PBMAIN
!mov edx,rngh
!shr edx,1
!mov eax,rng
!mov ecx,eax
!rcr ecx,1
!rcl edx,1
!mov rngh,edx
!shl eax,12
!xor ecx,eax
!mov eax,ecx
!shr eax,20
!xor ecx,eax
!mov rng,ecx
'!mov VariableWhereItsNeeded&,ecx
k = RND(0,65535) * 65536 + RND(0,65535)
m = rng AND &HFFFFFFFF 'Paul Dixon's result
m = m XOR k 'Mix it with PB's RND() result...
'to get a number that has a very high degree of 'randomness'
FUNCTION = m
END FUNCTION
FUNCTION GetRandom2() AS DWORD
'Function generates a pseudo random number using the CPU timestamp.
'Pre-pentium processors do not have the RDTSC command. Use routine
'HasRDTSC& to check this.
'
LOCAL i AS DWORD
STATIC m AS DWORD 'static to remember value for next function call
'Get CPU timestamp (only for Pentium processors)
! db &H0F, &HA2 ; CPUID < clear pipeline
! db &H0F, &H31 ; RDTSC < get timer
! mov i, eax ; get 32 low order bits
' edx contains 32 high order bits, ignore these
'Rotate i right a random nr of times
ROTATE RIGHT i, RND(1,24)
'Rotate previous result left a random nr of times
ROTATE LEFT m, RND(1,24)
'Combine the 2 values into a new random value
m = i XOR m
FUNCTION = m
END FUNCTION
FUNCTION HasRDTSC&
'-- Determines if the RDTSC processor instruction is available
! mov eax, 1 ;function 1
! cpuid
! xor eax, eax
! test edx, &b10000 ;bit 5
! setnz al
! mov function, eax
END FUNCTION
' The main function just generates a file filled with pseudo random bytes.
FUNCTION PBMAIN()
LOCAL LoopCtr AS LONG
LOCAL rn AS DWORD
LOCAL i AS LONG
LOCAL FileName AS STRING
LOCAL RoutineToUse AS LONG
LOCAL answer AS STRING
answer = INPUTBOX$("Which routine do you want to use? 1 or 2")
RoutineToUse = VAL(answer)
IF ISFALSE(HasRDTSC&) THEN
MSGBOX "This processor does not know the 'RDTSC' command."
RoutineToUse = 1
END IF
RANDOMIZE TIMER
LoopCtr=3000000 ' nr of longwords to generate
' this one about 12MB
FileName = "D:\Eddy\Crypto\RandomTests\Diehard\a" '<---change to your needs
KILL FileName
OPEN FileName FOR BINARY AS #1
MSGBOX "using routine" & STR$(RoutineToUse)
SELECT CASE RoutineToUse
CASE 1
FOR i=1 TO LoopCtr
rn = GetRandom1
PUT #1,, rn
NEXT
CASE 2
FOR i=1 TO LoopCtr
rn = GetRandom2
PUT #1,, rn
NEXT
END SELECT
CLOSE #1
MSGBOX "Finished!"
END FUNCTION