2024-04-29

Navigation

Skip Navigation Links

Hash algorithms

Asymmetric Algorithms

Symmetric Cipher Algorithms

Encoding Algorithms

Compression Algorithms

Pseudo Random Number Algorithms

Steganography

Library Wrappers

String Comparison

Others

Syntax highlighting by Prism
PBCrypto.com Mirror

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

Mirror provided by Knuth Konrad