Random Numbers

General FreeBASIC programming questions.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: Random Numbers

Postby MichaelW » Oct 27, 2015 2:34

Why not use a source of cryptographic random numbers, from CryptGenRandom for example, or the RDRAND instruction, and forget about "conditioning" the numbers.
RockTheSchock
Posts: 226
Joined: Mar 12, 2006 16:25

Re: Random Numbers

Postby RockTheSchock » Oct 27, 2015 7:51

Why dont you use the algorithm 5 as parameter?
RANDOMIZE TIMER,5

Call this once and rnd should generate very random numbers.
albert
Posts: 5533
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Random Numbers

Postby albert » Oct 27, 2015 17:05

I switched it back to INT(RND*GarbageBits) So go to projects page and redownload it...

It was stagnant on the first few bytes and not changing ,
The output should change everytime you click Cypher, If GarbageBytes is greater than 1.
As the garbagebits are changed with each click of "Cypher".
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: Random Numbers

Postby MichaelW » Oct 30, 2015 0:15

[code file=cpufeature.bi]
''-----------------------------------------------------------------------------
'' This assigns symbols to the bit index values for the ECX and EDX registers
'' as returned by CPUID Function 1. The names are from the Intel manual with
'' "-", ".", and whitespace replaced with "_", converted to upper case, and
'' uniformly prefixed with "_" to avoid reserved words. The added displacement
'' on the EDX values prevents them from overlapping the ECX values.
''-----------------------------------------------------------------------------

#define _SSE3 0
#define _PCLMULQDQ 1
#define _DTES64 2
#define _MONITOR 3
#define _DS_CPL 4
#define _VMX 5
#define _SMX 6
#define _EIST 7
#define _TM2 8
#define _SSSE3 9
#define _CNXT_ID 10
#define _SDBG 11
#define _FMA 12
#define _CMPXCHG16B 13
#define _XTPR_UPDATE_CONTROL 14
#define _PDCM 15
#define _PCID 17
#define _DCA 18
#define _SSE4_1 19
#define _SSE4_2 20
#define _X2APIC 21
#define _MOVBE 22
#define _POPCNT 23
#define _TSC_DEADLINE 24
#define _AESNI 25
#define _XSAVE 26
#define _OSXSAVE 27
#define _AVX 28
#define _F16C 29
#define _RDRAND 30

#define _FPU 0+32
#define _VME 1+32
#define _DE 2+32
#define _PSE 3+32
#define _TSC 4+32
#define _MSR 5+32
#define _PAE 6+32
#define _MCE 7+32
#define _CX8 8+32
#define _APIC 9+32
#define _SEP 11+32
#define _MTRR 12+32
#define _PGE 13+32
#define _MCA 14+32
#define _CMOV 15+32
#define _PAT 16+32
#define _PSE_36 17+32
#define _PSN 18+32
#define _CLFSH 19+32
#define _DS 21+32
#define _ACPI 22+32
#define _MMX 23+32
#define _FXSR 24+32
#define _SSE 25+32
#define _SSE2 26+32
#define _SS 27+32
#define _HTT 28+32
#define _TM 29+32
#define _PBE 31+32
[/code]
[code file=cpufeatures.bas]
#include "CpuFeature.bi"

''----------------------------------------------------------------------------
'' This function accepts a bit index value, as specified in CpuFeature.bi,
'' and returns the value of the indexed bit, 1 if the feature is supported
'' or 0 if the feature is not supported.
''
'' Since the most recent 1.04 manual does not explain 64-bit inline assembly
'' in a naked function, I'll provide a quick explanation. For the Microsoft
'' X64 calling convention, for integer or pointer parameters and integer
'' return values, the first four parameters are passed in RCX, RDX, R8, and
'' R9, the return register is RAX, the scratch registers are RAX, RCX, RDX,
'' and R8-R11, and the callee-save registers are RBX, RSI, RDI, RBP, and
'' R12-R15.
''----------------------------------------------------------------------------

function CpuFeature naked ( index as integer ) as integer
asm
mov r8, rcx '' copy index to register that CPUID will not alter
mov rax, 1 '' set the CPUID function number
push rbx '' preserve RBX (because CPUID will alter EBX)
cpuid '' execute CPUID
pop rbx '' recover RBX
xor rax, rax '' zero return register
cmp r8, 31 '' determine if target register is ECX or EDX
ja 0f '' jump if target is EDX
bt rcx, r8 '' get indexed bit into the carry flag
adc rax, 0 '' copy indexed bit to return register
ret '' return to the caller
0:
sub r8, 32 '' remove displacement from index
bt rdx, r8 '' get indexed bit into the carry flag
adc rax, 0 '' copy indexed bit to return register
ret '' return to the caller
end asm
end function

''----------------------------------------------------------------------------
'' This code displays all of the processor feature information returned by
'' CPUID function 1 in the ECX and EDX registers.
''----------------------------------------------------------------------------

print "SSE3 ", CpuFeature(_SSE3)
print "PCLMULQDQ ", CpuFeature(_PCLMULQDQ)
print "DTES64 ", CpuFeature(_DTES64)
print "MONITOR ", CpuFeature(_MONITOR)
print "DS_CPL ", CpuFeature(_DS_CPL)
print "VMX ", CpuFeature(_VMX)
print "SMX ", CpuFeature(_SMX)
print "EIST ", CpuFeature(_EIST)
print "TM2 ", CpuFeature(_TM2)
print "SSSE3 ", CpuFeature(_SSSE3)
print "CNXT_ID ", CpuFeature(_CNXT_ID)
print "SDBG ", CpuFeature(_SDBG)
print "FMA ", CpuFeature(_FMA)
print "CMPXCHG16B ", CpuFeature(_CMPXCHG16B)
print "XTPR_UPDATE_CONTROL ", CpuFeature(_XTPR_UPDATE_CONTROL)
print "PDCM ", CpuFeature(_PDCM)
print "PCID ", CpuFeature(_PCID)
print "DCA ", CpuFeature(_DCA)
print "SSE4_1 ", CpuFeature(_SSE4_1)
print "SSE4_2 ", CpuFeature(_SSE4_2)
print "X2APIC ", CpuFeature(_X2APIC)
print "MOVBE ", CpuFeature(_MOVBE)
print "POPCNT ", CpuFeature(_POPCNT)
print "TSC_DEADLINE ", CpuFeature(_TSC_DEADLINE)
print "AESNI ", CpuFeature(_AESNI)
print "XSAVE ", CpuFeature(_XSAVE)
print "OSXSAVE ", CpuFeature(_OSXSAVE)
print "AVX ", CpuFeature(_AVX)
print "F16C ", CpuFeature(_F16C)
print "RDRAND ", CpuFeature(_RDRAND)
print
print "FPU ", CpuFeature(_FPU)
print "VME ", CpuFeature(_VME)
print "DE ", CpuFeature(_DE)
print "PSE ", CpuFeature(_PSE)
print "TSC ", CpuFeature(_TSC)
print "MSR ", CpuFeature(_MSR)
print "PAE ", CpuFeature(_PAE)
print "MCE ", CpuFeature(_MCE)
print "CX8 ", CpuFeature(_CX8)
print "APIC ", CpuFeature(_APIC)
print "SEP ", CpuFeature(_SEP)
print "MTRR ", CpuFeature(_MTRR)
print "PGE ", CpuFeature(_PGE)
print "MCA ", CpuFeature(_MCA)
print "CMOV ", CpuFeature(_CMOV)
print "PAT ", CpuFeature(_PAT)
print "PSE_36 ", CpuFeature(_PSE_36)
print "PSN ", CpuFeature(_PSN)
print "CLFSH ", CpuFeature(_CLFSH)
print "DS ", CpuFeature(_DS)
print "ACPI ", CpuFeature(_ACPI)
print "MMX ", CpuFeature(_MMX)
print "FXSR ", CpuFeature(_FXSR)
print "SSE ", CpuFeature(_SSE)
print "SSE2 ", CpuFeature(_SSE2)
print "SS ", CpuFeature(_SS)
print "HTT ", CpuFeature(_HTT)
print "TM ", CpuFeature(_TM)
print "PBE ", CpuFeature(_PBE)

sleep
[/code]

Edit: Added CryptReleaseContext call and revised the comments.
[code file=random.bas]
#include "windows.bi"
#include "win\wincrypt.bi"
#include "CpuFeature.bi"

''----------------------------------------------------------------------------
'' This function accepts a bit index value, as specified in CpuFeature.bi,
'' and returns the value of the indexed bit, 1 if the feature is supported
'' or 0 if the feature is not supported.
''
'' Since the most recent 1.04 manual does not explain 64-bit inline assembly
'' in a naked function, I'll provide a quick explanation. For the Microsoft
'' X64 calling convention, for integer or pointer parameters and integer
'' return values, the first four parameters are passed in RCX, RDX, R8, and
'' R9, the return register is RAX, the scratch registers are RAX, RCX, RDX,
'' and R8-R11, and the callee-save registers are RBX, RSI, RDI, RBP, and
'' R12-R15.
''----------------------------------------------------------------------------

function CpuFeature naked ( index as integer ) as integer
asm
mov r8, rcx '' copy index to register that CPUID will not alter
mov rax, 1 '' set the CPUID function number
push rbx '' preserve RBX (because CPUID will alter EBX)
cpuid '' execute CPUID
pop rbx '' recover RBX
xor rax, rax '' zero return register
cmp r8, 31 '' determine if target register is ECX or EDX
ja 0f '' jump if target is EDX
bt rcx, r8 '' get indexed bit into the carry flag
adc rax, 0 '' copy indexed bit to return register
ret '' return to the caller
0:
sub r8, 32 '' remove displacement from index
bt rdx, r8 '' get indexed bit into the carry flag
adc rax, 0 '' copy indexed bit to return register
ret '' return to the caller
end asm
end function

function RdRand64 naked() as integer
asm
0:
rdrand rax '' store 64-bit randon number in return register
jnc 0b '' repeat until a valid random number has been returned
ret '' return to the caller
end asm
end function

''--------------------------------------------------------------------------
'' This function returns a 64-bit cryptographic random number, generated by
'' the RDRAND instruction if supported, or otherwise by the default CSP.
''--------------------------------------------------------------------------

function GenRand() as integer

dim hProv as HCRYPTPROV
dim as integer rand64

static as integer rdrand_tested, rdrand_ok

''-----------------------------------------------------------
'' Since the CpuFeature function is very slow, mostly due to
'' the CPUID instruction, limit it to a single call.
''-----------------------------------------------------------

if rdrand_tested = 0 then
rdrand_ok = CpuFeature(_RDRAND)
rdrand_tested = -1
end if

if rdrand_ok then
return RdRand64()
else
if CryptAcquireContext( @hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) = 0 then
print "Error calling CryptAcquireContext"
sleep
end
else
if CryptGenRandom( hProv, 8, cast(BYTE ptr, @rand64) ) then
CryptReleaseContext( hProv,0 )
return rand64
else
print "Error calling CryptGenRandom"
sleep
end
end if

end if
end if
end function

for i as integer = 1 to 100
print hex(GenRand(),16)
next

sleep
[/code]
albert
Posts: 5533
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Random Numbers

Postby albert » Oct 30, 2015 21:45

@MichaelW

How do you getit to pick from a range, like : pick 100 numbers between 1 and 4096.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: Random Numbers

Postby MichaelW » Oct 30, 2015 23:22

albert wrote:How do you getit to pick from a range, like : pick 100 numbers between 1 and 4096.

This appears to work correctly, substituted into the above code:

Code: Select all

''--------------------------------------------------------------------------
'' This function returns a 64-bit cryptographic random number, generated by
'' the RDRAND instruction if supported, or otherwise by the default CSP.
''--------------------------------------------------------------------------

function GenRand() as uinteger

    dim hProv as HCRYPTPROV
    dim as uinteger rand64
   
    static as integer rdrand_tested, rdrand_ok
   
    ''---------------------------------------------------------------
    '' Avoid calling CpuFeature for each random number because the
    '' function, mostly due to the CPUID instruction, is very slow.
    ''---------------------------------------------------------------
   
    if rdrand_tested = 0 then
        rdrand_ok = CpuFeature(_RDRAND)
        rdrand_tested = -1
    end if   
   
    if rdrand_ok then
        return RdRand64()
    else
        if CryptAcquireContext( @hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) = 0 then
            print "Error calling CryptAcquireContext"
            sleep
            end
        else
            if CryptGenRandom( hProv, 8, cast(BYTE ptr, @rand64) ) then
                return rand64
            else   
                print "Error calling CryptGenRandom"
                sleep
                end
            end if   

        end if   
    end if
end function

function Restrict( random_number as uinteger, _
                   lower_limit as uinteger, _
                   upper_limit as uinteger ) as uinteger
    return random_number mod (upper_limit - lower_limit + 1) + lower_limit
end function   

dim as uinteger r, minimum = &hffffffffffffffff, maximum, sum

for i as integer = 1 to 10000000
    r = Restrict(GenRand(), 1, 4096)
    if r > maximum then maximum = r
    if r < minimum then minimum = r
    sum += r   
next   
print minimum
print maximum
print sum / 10000000

sleep

Code: Select all

1
4096
 2048.1829947

But note that MOD is relatively slow, as is the CryptGenRandom function when you request one random number per call.
albert
Posts: 5533
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Random Numbers

Postby albert » Oct 31, 2015 2:53

@MichaelW

Thanks for the code. I'll see about using it in Version 10. I'm done with Version 9.
albert
Posts: 5533
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Random Numbers

Postby albert » Oct 31, 2015 17:39

@MichaelW

your RDRAND returns just about the same as regular INT(RND*GarbageBits)

Code: Select all


#include "windows.bi"
#include "win\wincrypt.bi"
#include "CpuFeature.bi"

''----------------------------------------------------------------------------
'' This function accepts a bit index value, as specified in CpuFeature.bi,
'' and returns the value of the indexed bit, 1 if the feature is supported
'' or 0 if the feature is not supported.
''
'' Since the most recent 1.04 manual does not explain 64-bit inline assembly
'' in a naked function, I'll provide a quick explanation. For the Microsoft
'' X64 calling convention, for integer or pointer parameters and integer
'' return values, the first four parameters are passed in RCX, RDX, R8, and
'' R9, the return register is RAX, the scratch registers are RAX, RCX, RDX,
'' and R8-R11, and the callee-save registers are RBX, RSI, RDI, RBP, and
'' R12-R15.
''----------------------------------------------------------------------------

function CpuFeature naked ( index as integer ) as integer
    asm
        mov     r8, rcx   '' copy index to register that CPUID will not alter
        mov     rax, 1    '' set the CPUID function number
        push    rbx       '' preserve RBX (because CPUID will alter EBX)
        cpuid             '' execute CPUID
        pop     rbx       '' recover RBX
        xor     rax, rax  '' zero return register
        cmp     r8, 31    '' determine if target register is ECX or EDX
        ja      0f        '' jump if target is EDX
        bt      rcx, r8   '' get indexed bit into the carry flag
        adc     rax, 0    '' copy indexed bit to return register
        ret               '' return to the caller 
      0:
        sub     r8, 32    '' remove displacement from index
        bt      rdx, r8   '' get indexed bit into the carry flag
        adc     rax, 0    '' copy indexed bit to return register
        ret               '' return to the caller
    end asm
end function

function RdRand64 naked() as integer
    asm
      0:
        rdrand    rax
        jnc       0b
        ret       
    end asm
end function

''--------------------------------------------------------------------------
'' This function returns a 64-bit cryptographic random number, generated by
'' the RDRAND instruction if supported, or otherwise by the default CSP.
''--------------------------------------------------------------------------

function GenRand() as uinteger

    dim hProv as HCRYPTPROV
    dim as uinteger rand64
   
    static as integer rdrand_tested, rdrand_ok
   
    ''---------------------------------------------------------------
    '' Avoid calling CpuFeature for each random number because the
    '' function, mostly due to the CPUID instruction, is very slow.
    ''---------------------------------------------------------------
   
    if rdrand_tested = 0 then
        rdrand_ok = CpuFeature(_RDRAND)
        rdrand_tested = -1
    end if   
   
    if rdrand_ok then
        return RdRand64()
    else
        if CryptAcquireContext( @hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) = 0 then
            print "Error calling CryptAcquireContext"
            sleep
            end
        else
            if CryptGenRandom( hProv, 8, cast(BYTE ptr, @rand64) ) then
                return (rand64)
            else   
                print "Error calling CryptGenRandom"
                sleep
                end
            end if   

        end if   
    end if
end function

function Restrict( random_number as ulongint, _
                   lower_limit as ulongint, _
                   upper_limit as ulongint ) as ulongint
    return random_number mod (upper_limit - lower_limit + 1) + lower_limit
end function   

Sub GenerateKey1()
   
    dim as longint TabPages = 128
    dim as longint Garbagebits = 128*8*(TabPages*8)
   
    Redim as longint Key(0 to (TabPages*64-1) )
       
    dim a as longint
    dim b as longint
    dim c as longint
    dim d as longint
 
    'create random key for main cypher.
    for a = 0 to (TabPages*64)-1
        key(a) = 0
    next
     
    a=0
    do
        'b = int(rnd*GarbageBits)+1
        randomize b * sin(rnd*timer) / tan(timer/1000)
        do 
            b = int(rnd*GarbageBits)
            d = 0
            for c = 0 to a
               if key(c) = b then d = 1
            next
        loop until d = 0
        key(a) = b
        a = a + 1     
    loop until a=(TabPages*64)     

    dim as longint count(1 to 8)
    for a as longint = lbound(key) to ubound(key)
        'print key(a) ,
        dim as string num = str(key(a))
        if len(num) = 1 then count(1)+=1
        if len(num) = 2 then count(2)+=1
        if len(num) = 3 then count(3)+=1
        if len(num) = 4 then count(4)+=1
        if len(num) = 5 then count(5)+=1
        if len(num) = 6 then count(6)+=1
        if len(num) = 7 then count(7)+=1
        if len(num) = 8 then count(8)+=1
    next
   
    print "Int(rnd*GatbageBits)"
    print "Digits = 1 " ; count(1)
    print "Digits = 2 " ; count(2)
    print "Digits = 3 " ; count(3)
    print "Digits = 4 " ; count(4)
    print "Digits = 5 " ; count(5)
    print "Digits = 6 " ; count(6)
    print "Digits = 7 " ; count(7)
    print "Digits = 8 " ; count(8)
    print
   
End Sub

Sub GenerateKey2()
   
    dim as longint TabPages = 128
    dim as longint Garbagebits = 128*8*(TabPages*8)
   
    Redim as longint Key(0 to (TabPages*64-1) )
       
    dim a as longint
    dim b as longint
    dim c as longint
    dim d as longint
 
    'create random key for main cypher.
    for a = 0 to (TabPages*64)-1
        key(a) = 0
    next
     
    a=0
    do
        'b = int(rnd*GarbageBits)+1
        randomize b * sin(rnd*timer) / tan(timer/1000)
        do 
            'b = int(rnd*GarbageBits)
            b = Restrict(GenRand(), 1, GarbageBits)
            d = 0
            for c = 0 to a
               if key(c) = b then d = 1
            next
        loop until d = 0
        key(a) = b
        a = a + 1     
    loop until a=(TabPages*64)     

    dim as longint count(1 to 8)
    for a as longint = lbound(key) to ubound(key)
        'print key(a) ,
        dim as string num = str(key(a))
        if len(num) = 1 then count(1)+=1
        if len(num) = 2 then count(2)+=1
        if len(num) = 3 then count(3)+=1
        if len(num) = 4 then count(4)+=1
        if len(num) = 5 then count(5)+=1
        if len(num) = 6 then count(6)+=1
        if len(num) = 7 then count(7)+=1
        if len(num) = 8 then count(8)+=1
    next
   
    Print "MichaelW"
    print "Digits = 1 " ; count(1)
    print "Digits = 2 " ; count(2)
    print "Digits = 3 " ; count(3)
    print "Digits = 4 " ; count(4)
    print "Digits = 5 " ; count(5)
    print "Digits = 6 " ; count(6)
    print "Digits = 7 " ; count(7)
    print "Digits = 8 " ; count(8)
    print
End Sub

GenerateKey1()
GenerateKey2()

sleep
end

MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: Random Numbers

Postby MichaelW » Nov 02, 2015 6:54

albert wrote:your RDRAND returns just about the same as regular INT(RND*GarbageBits)

Define "just about the same".

RDRAND returns a hardware-generated random number.

https://en.wikipedia.org/wiki/RdRand

While I could not access reference 7 on the Wikipedia page, reference 6 includes a description of the generator.
albert
Posts: 5533
Joined: Sep 28, 2006 2:41
Location: California, USA

Re: Random Numbers

Postby albert » Nov 02, 2015 17:20

@MichaelW

You must not have run the above code.
The outputs of both methods are just about the same numbers of digits.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: Random Numbers

Postby MichaelW » Nov 02, 2015 21:54

albert wrote:The outputs of both methods are just about the same numbers of digits.

Which indicates that both methods return sequences that are more or less uniformly distributed, but consider that it's possible to create non-random sequences that have a perfect uniform distribution.

Return to “General”

Who is online

Users browsing this forum: MSN [Bot] and 4 guests