Random

From NSIS Wiki
Jump to navigationJump to search
Author: nechai (talk, contrib)


Description

Linear Congruential Generator
Park, S.K. and K.W. Miller, 1988; Random Number Generators: Good Ones are Hard to Find,
Comm. of the ACM, V. 31. No. 10, pp 1192-1201
n(k+1) = (a * n(k) + b) mod m
m=2147483647, a=16807, b=0 
the seed after 10000 iterations should be 1043618065 for n(0)=1
http://www.mactech.com/articles/mactech/Vol.08/08.03/RandomNumbers/

Syntax

${Random} "Seed" "Min" "Max

"Seed"     ; Seed value for generator or last generated random number
"Min"      ; name of the initialization file
"Max"      ; Callback function then found

Stack 1    ; Random number between 0x00000000 and 0X7FFFFFFF [0x00000000;0X7FFFFFFF]
Stack 2    ; Random number between Min and Max [MIN;MAX]

Usage

 Do:
     IntOp $0 $0 + 1
     ${Random} $1 0 255
     Pop $1
     Pop $2
     StrCmp $0 "10000" 0 Do
 StrCmp $1 1043618065 0 +2
     MessageBox MB_OK "Test Minimal Standard Generator o.k."

The Function

Function Random
; Linear Congruential Generator
; Park, S.K. and K.W. Miller, 1988; Random Number Generators: Good Ones are Hard to Find,
; Comm. of the ACM, V. 31. No. 10, pp 1192-1201
; n(k+1) = (a * n(k) + b) mod m
; m=2147483647, a=16807, b=0 
; the seed after 10000 iterations should be 1043618065 for n(0)=1
; http://www.mactech.com/articles/mactech/Vol.08/08.03/RandomNumbers/
; 
; Syntax:
; ${Random} "Seed" "Min" "Max
; 
; "Seed"     ; Seed value for generator or last generated random number
; "Min"      ; name of the initialization file
; "Max"      ; Callback function then found
; 
; Stack 1    ; Random number between 0x00000000 and 0X7FFFFFFF [0x00000000;0X7FFFFFFF]
; Stack 2    ; Random number between min and max [MIN;MAX]
; 
; e.g.
; Do:
;     IntOp $0 $0 + 1
;     ${Random} $1 0 255
;     Pop $1
;     Pop $2
;     StrCmp $0 "10000" 0 Do
; StrCmp $1 1043618065 0 +2
;     MessageBox MB_OK "Test Minimal Standard Generator o.k."
;
    !define Random `!insertmacro RandomCall`
 
    !macro RandomCall _SEED _MIN _MAX
        ; save global registers
        Push $0
        Push $1
        Push $2
        Push $3
        Push $4
        Push $5
        Push $6
        Push $7
        Push $8
        Push $9		
        ; store parameter
        Push `${_SEED}`
        Push `${_MIN}`
        Push `${_MAX}`
        ; execute function
	Call Random
        ; restore global register
        Pop $9
        Pop $8
        Pop $7
        Pop $6
        Pop $5
        Pop $4
        Pop $3
        Pop $2
	Exch $1
        Exch
        Exch $0
    !macroend
Function Random
    Pop $2 ; _MAX
    Pop $1 ; _MIN
    Pop $0 ; _SEED
 
    ; n(k+1) = (a * n(k) + b) mod m
    System::Int64Op /NOUNLOAD 16807 * $0
    Pop $0
    System::Int64Op /NOUNLOAD $0 + 0
    Pop $0
    System::Int64Op /NOUNLOAD $0 % 0X7FFFFFFF
    Pop $0
 
    ; calculate value betwenn _MIN _MAX
    IntOp $3 $2 - $1
    IntOp $3 $3 + 1
    System::Int64Op /NOUNLOAD $0 * $3
    Pop $4
    System::Int64Op /NOUNLOAD $4 / 0X7FFFFFFF
    Pop $4
    IntOp $1 $4 + $1
 
FunctionEnd