- Here is an attempt at recreating the AHK v2 Random and RandomSeed functions (equivalent to the AHK v1 Random command).

Code: Select all

```
q:: ;recreate Random and RandomSeed
vSeed := 1337
Random,, % vSeed
JEE_RandomSeed(vSeed)
vMin := 0, vMax := 2147483647
vMin := -2147483648, vMax := 2147483647
vMin := 0.0, vMax := 1.0
vMin := 0.0, vMax := 100.0
vMin := -2147483648.0, vMax := 2147483647.0
vOutput := ""
Loop, 10
{
Random, vTemp1, % vMin, % vMax
vTemp2 := JEE_Random(vMin, vMax)
vOutput .= vTemp1 "`r`n" vTemp2 "`r`n`r`n"
if !(vTemp1 = vTemp2)
MsgBox, % "mismatch:`r`n" vTemp1 "`r`n" vTemp2
}
MsgBox, % Clipboard := vOutput
return
e::
vIntervals := 0
DllCall("kernel32\GetSystemTimeAsFileTime", Int64P,vIntervals)
vSeed := vIntervals & 0xFFFFFFFF
vSeed := 1337
Random_init_genrand(vSeed)
MsgBox, % vSeed "`r`n" Random_genrand_int32()
Random,, % vSeed
Random, vNum
MsgBox, % vSeed "`r`n" vNum
return
w::
vNum := 1000000
vNum := 1000
Loop, % 0xFFFFFFFF + 1
{
ToolTip, % A_Index
vSeed := A_Index - 1
Random,, % vSeed
;vOutput1 := "AHK" "`r`n"
vOutput1 := ""
Loop, % vNum
{
Random, vTemp
vOutput1 .= vTemp "`r`n"
}
Random_init_genrand(vSeed)
;vOutput2 := "CUSTOM" "`r`n"
vOutput2 := ""
Loop, % vNum
{
vTemp := Random_genrand_int32()
if (vTemp >= 2147483648)
vTemp -= 2147483648
vOutput2 .= vTemp "`r`n"
}
if !(vOutput1 = vOutput2)
{
MsgBox, % "mismatch for seed: " vSeed
;JEE_WinMergeCompareStrings(vOutput1, vOutput2)
}
}
MsgBox, % "done"
return
;==================================================
;Random_XXX functions based on AHK source code (mt19937ar-cok.cpp)
;Random - Syntax & Usage | AutoHotkey
;https://autohotkey.com/docs/commands/Random.htm
;/*
; C++ functions for MT19937, with initialization improved 2002/2/10.
; Coded by Takuji Nishimura and Makoto Matsumoto.
; This is a faster version by taking Shawn Cokus's optimization,
; Matthe Bellew's simplification, Isaku Wada's real version.
; Before using, initialize the state by using init_genrand(seed)
; or init_by_array(init_key, key_length).
; Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
; All rights reserved.
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
; are met:
; 1. Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; 2. Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; 3. The names of its contributors may not be used to endorse or promote
; products derived from this software without specific prior written
; permission.
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
; Any feedback is very welcome.
; http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
; email: [email protected]
;*/
;==================================================
Random_MIXBITS(u,v)
{
local
UMASK := 0x80000000
LMASK := 0x7fffffff
return (u & UMASK) | (v & LMASK)
}
Random_TWIST(u,v)
{
local
MATRIX_A := 0x9908b0df
return (Random_MIXBITS(u,v) >> 1) ^ ((v&1) ? MATRIX_A : 0)
}
Random_init_genrand(s)
{
local
global g_Rand, g_RandState
static N := 624
g_Rand := {}
g_RandState := []
g_RandState.SetCapacity(N)
g_RandState.Push(s & 0xffffffff)
Loop, % N-1
{
j := A_Index+1
temp := (1812433253 * (g_RandState[j-1] ^ (g_RandState[j-1] >> 30)) + j-1)
g_RandState.Push(temp & 0xffffffff)
}
g_Rand.left := 1
g_Rand.initf := 1
}
Random_next_state()
{
local
global g_Rand, g_RandState
static M := 397, N := 624
if !IsObject(g_Rand)
g_Rand := {}
g_Rand.left := N
g_Rand.next := 1
if !g_Rand.initf
{
vTickCount := DllCall("kernel32\GetTickCount", UInt)
Random_init_genrand(vTickCount)
;vIntervals := 0
;DllCall("kernel32\GetSystemTimeAsFileTime", Int64P,vIntervals)
;Random_init_genrand(vIntervals & 0xFFFFFFFF)
}
temp := 0
Loop, % N-M
temp += 1, g_RandState[temp] := g_RandState[temp+M] ^ Random_TWIST(g_RandState[temp], g_RandState[temp+1])
Loop, % M-1
temp += 1, g_RandState[temp] := g_RandState[temp+M-N] ^ Random_TWIST(g_RandState[temp], g_RandState[temp+1])
temp += 1, g_RandState[temp] := g_RandState[temp+M-N] ^ Random_TWIST(g_RandState[temp], g_RandState.1)
}
Random_genrand_int32()
{
local
global g_Rand, g_RandState
if !IsObject(g_Rand)
g_Rand := {}
if (--g_Rand.left == 0)
Random_next_state()
y := g_RandState[g_Rand.next++]
y ^= (y >> 11)
y ^= (y << 7) & 0x9d2c5680
y ^= (y << 15) & 0xefc60000
y ^= (y >> 18)
return y ;a random number on [0,0xffffffff]-interval
}
Random_genrand_int31()
{
local
global g_Rand, g_RandState
if !IsObject(g_Rand)
g_Rand := {}
if (--g_Rand.left == 0)
Random_next_state()
y := g_RandState[g_Rand.next++]
y ^= (y >> 11)
y ^= (y << 7) & 0x9d2c5680
y ^= (y << 15) & 0xefc60000
y ^= (y >> 18)
return y >> 1 ;a random number on [0,0x7fffffff]-interval
}
Random_genrand_real1()
{
local
global g_Rand, g_RandState
if !IsObject(g_Rand)
g_Rand := {}
if (--g_Rand.left == 0)
Random_next_state()
y := g_RandState[g_Rand.next++]
y ^= (y >> 11)
y ^= (y << 7) & 0x9d2c5680
y ^= (y << 15) & 0xefc60000
y ^= (y >> 18)
return y * (1/4294967295) ;a random number on [0,1]-real-interval
}
;range: 0 to 4294967295
JEE_RandomSeed(vSeed)
{
local
Random_init_genrand(vSeed)
}
;range: -2147483648 to 2147483647 (for integers)
;range: no limit (for floats)
JEE_Random(vMin:=0, vMax:=2147483647)
{
local
vIsFloat := !!(InStr(vMin, ".") || InStr(vMax, "."))
if (vMin > vMax)
vTemp := vMin, vMin := vMax, vMax := vTemp
if vIsFloat
return Random_genrand_real1() * (vMax - vMin) + vMin
return Mod(Random_genrand_int32(), vMax - vMin + 1) + vMin
}
```

- @DRocks: Thanks.

- Curiously the source code uses GetTickCount in one place, but GetSystemTimeAsFileTime in another.