Skip to content

Instantly share code, notes, and snippets.

@aike
Last active August 3, 2021 21:15
Show Gist options
  • Save aike/d0d0a5a12c265c5e1fbd07d793919185 to your computer and use it in GitHub Desktop.
Save aike/d0d0a5a12c265c5e1fbd07d793919185 to your computer and use it in GitHub Desktop.
KSP random function benchmark / 10000 loop result: random() 827microsec, LCG 857microsec, MT 11498microsec
{==========================================
random function benchmark
==========================================}
on init
set_ui_height_px(120)
make_perfview
set_script_title("random function benchmark")
declare ui_label $label1(1, 1)
declare ui_label $label2(1, 1)
declare ui_label $label3(1, 1)
move_control($label1, 1, 2)
move_control($label2, 1, 3)
move_control($label3, 1, 4)
set_text($label1, "random")
set_text($label2, "MT")
set_text($label3, "LCG")
declare ui_label $result1(1, 1)
declare ui_label $result2(1, 1)
declare ui_label $result3(1, 1)
move_control($result1, 2, 2)
move_control($result2, 2, 3)
move_control($result3, 2, 4)
set_text($result1, "")
set_text($result2, "")
set_text($result3, "")
declare $n
declare $r
declare const $loop := 10000
{==========================================
Linear Congruential Generator
==========================================}
{ LCG access variables }
declare $lcg_seed
$lcg_seed := 0
declare $lcg_rand
declare $lcg_next
{==========================================
Mersenne Twister (MT19937)
==========================================}
{ MT access variables }
declare $mt_seed
$mt_seed := 0
declare $mt_rand
{ MT xor helper variables }
declare $mt_xor_arg1
declare $mt_xor_arg2
declare $mt_xor_tmp_or
declare $mt_xor_tmp_nand
declare $mt_xor_result
{ MT Period parameters }
declare const $mt_N := 624
declare const $mt_M := 397
declare const $mt_MATRIX_A := 09908b0dfh
declare const $mt_UPPER_MASK := 080000000h
declare const $mt_LOWER_MASK := 07fffffffh
declare %mt_x[$mt_N]
declare $mt_i
declare $mt_y
declare $mt_z
{ MT initialize array with $mt_seed }
%mt_x[0] := $mt_seed .and. 0ffffffffh
$mt_i := 1
while ($mt_i < $mt_N)
$mt_xor_arg1 := %mt_x[$mt_i - 1]
$mt_xor_arg2 := sh_right(%mt_x[$mt_i - 1] .and. $mt_LOWER_MASK, 30)
if (%mt_x[$mt_i - 1] < 0)
$mt_xor_arg2 := $mt_xor_arg2 .or. 2
end if
$mt_xor_tmp_or := $mt_xor_arg1 .or. $mt_xor_arg2
$mt_xor_tmp_nand := .not. ($mt_xor_arg1 .and. $mt_xor_arg2)
$mt_xor_result := $mt_xor_tmp_or .and. $mt_xor_tmp_nand
%mt_x[$mt_i] := (1812433253 * $mt_xor_result) + $mt_i
%mt_x[$mt_i] := %mt_x[$mt_i] .and. 0ffffffffh
inc($mt_i)
end while
$mt_i := 0
message("")
end on
{ MT helper function calculate $mt_xor_arg1 XOR $mt_xor_arg2 }
function mt_xor
$mt_xor_tmp_or := $mt_xor_arg1 .or. $mt_xor_arg2
$mt_xor_tmp_nand := .not. ($mt_xor_arg1 .and. $mt_xor_arg2)
$mt_xor_result := $mt_xor_tmp_or .and. $mt_xor_tmp_nand
end function
{ MT initialize array with $mt_seed }
function mt_init
%mt_x[0] := $mt_seed .and. 0ffffffffh
$mt_i := 1
while ($mt_i < $mt_N)
$mt_xor_arg1 := %mt_x[$mt_i - 1]
$mt_xor_arg2 := sh_right(%mt_x[$mt_i - 1] .and. $mt_LOWER_MASK, 30)
if (%mt_x[$mt_i - 1] < 0)
$mt_xor_arg2 := $mt_xor_arg2 .or. 2
end if
call mt_xor
%mt_x[$mt_i] := (1812433253 * $mt_xor_result) + $mt_i
%mt_x[$mt_i] := %mt_x[$mt_i] .and. 0ffffffffh
inc($mt_i)
end while
$mt_i := 0
end function
{ MT generates a random number }
function mt_genrand
$mt_z := %mt_x[$mt_i] .and. $mt_UPPER_MASK
$mt_z := $mt_z .or. (%mt_x[($mt_i + 1) mod $mt_N] .and. $mt_LOWER_MASK)
$mt_xor_arg1 := %mt_x[($mt_i + $mt_M) mod $mt_N]
$mt_xor_arg2 := sh_right($mt_z .and. $mt_LOWER_MASK, 1)
if ($mt_z < 0)
$mt_xor_arg2 := $mt_xor_arg2 .or. 040000000h
end if
call mt_xor
$mt_xor_arg1 := $mt_xor_result
if (($mt_z .and. 1) = 0)
$mt_xor_arg2 := 0
else
$mt_xor_arg2 := $mt_MATRIX_A
end if
call mt_xor
%mt_x[$mt_i] := $mt_xor_result
$mt_y := %mt_x[$mt_i]
{ Tempering }
$mt_xor_arg1 := $mt_y
$mt_xor_arg2 := sh_right($mt_y .and. $mt_LOWER_MASK, 11)
if ($mt_y < 0)
$mt_xor_arg2 := $mt_xor_arg2 .or. 100000h
end if
call mt_xor
$mt_y := $mt_xor_result
$mt_xor_arg1 := $mt_y
$mt_xor_arg2 := sh_left($mt_y, 7) .and. 09d2c5680h
call mt_xor
$mt_y := $mt_xor_result
$mt_xor_arg1 := $mt_y
$mt_xor_arg2 := sh_left($mt_y, 15) .and. 0efc60000h
call mt_xor
$mt_y := $mt_xor_result
$mt_xor_arg1 := $mt_y
$mt_xor_arg2 := sh_right($mt_y .and. $mt_LOWER_MASK, 18)
if ($mt_y < 0)
$mt_xor_arg2 := $mt_xor_arg2 .or. 2000h
end if
call mt_xor
$mt_y := $mt_xor_result
{ get 31bit unsigned int }
$mt_rand := sh_right($mt_y .and. $mt_LOWER_MASK, 1)
if ($mt_y < 0)
$mt_rand := $mt_rand .or. 040000000h
end if
$mt_i := ($mt_i + 1) mod $mt_n
end function
{ LCG initialize array with $mt_seed }
function lcg_init
$lcg_next := $lcg_seed
end function
{ LCG generates a random number }
function lcg_genrand
$lcg_next := $lcg_next * 1103515245 + 12345
$lcg_rand := sh_right($lcg_next .and. 07fffffffh, 16)
end function
on note
reset_ksp_timer
$n := 0
while($n < $loop)
$r := random(0, 7fffh)
inc($n)
end while
set_text($result1, $KSP_TIMER & " microsec")
reset_ksp_timer
$n := 0
while($n < $loop)
call mt_genrand
$r := $mt_rand
inc($n)
end while
set_text($result2, $KSP_TIMER & " microsec")
reset_ksp_timer
$n := 0
while($n < $loop)
call lcg_genrand
$r := $lcg_rand
inc($n)
end while
set_text($result3, $KSP_TIMER & " microsec")
end on
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment