|
总有人抱怨jass自带的随机生成函数不够好,这个也许会好一些,但代价是更慢。
请允许我引用一下
Inversive Congruential Generators
Sometimes the Parallel Hyperplanes phenomenon inherentin LCGs may cause adverse effects to certain simulation applications becausethe space between the hyperplanes will never be hit by any point of thegenerator, and the simulation result may be very sensitive to this kind ofregularities. Inversive Congruential Generators (ICG) are designed to overcome this difficulty. It is a variant of LCG:
where if and . Tocalculate , one can apply the reverse of Euclid's algorithm to find integer solutions for .Although the extra inversion step eliminates Parallel Hyperplanes(see Figure 3), it alsochanges the intrinsic structures and correlation behaviors of LCGs [5]. ICGs are promising candidates for parallelization, becauseunlike LCGs, ICGs do not have long-range autocorrelations problems.However, at current state of the art, ICGs are substantially (8X) slower than LCGs due to the inversion process. ICGs have the same period as their LCG counterparts, i.e. .
注:ICG(逆同余生成器)即下面的,LCG(线性同余生成器)即原jass的(猜的)。
LCG
ICG
[codes=jass]
function ICG_GetInvert takes integer c returns integer
local integer s = 0
local integer t = 1
local integer n = c
local integer p = udg_ICG_max
local integer q = 0
if c == 0 then
set c = 1
endif
loop
set q = p / n
set s = s - q * t
set p = p - q * n
if p == 0 then
return t
endif
set q = n / p
set t = t - q * s
set n = n - q * p
if n == 0 then
return s
endif
endloop
return s
endfunction
function ICG_GetMult takes integer a, integer b returns integer
local integer q = 0
if a == 1 then
return b
elseif b <= udg_ICG_max / a then
return a * b
else
set q = udg_ICG_max / a
set b = a*ModuloInteger(b, q) - b/q*ModuloInteger(udg_ICG_max, a)
if b < 0 then
return b + udg_ICG_max
else
return b
endif
endif
return b
endfunction
function ICG_GetAdd takes integer a, integer b returns integer
if b <= udg_ICG_max - a then
return a + b
else
return b - udg_ICG_max + a
endif
return b
endfunction
function ICG_Seed takes integer s returns nothing
set udg_ICG_max = 2147483647
set udg_ICG_a = 9102
set udg_ICG_b = 2110599482
if s == 0 then
set udg_ICG_seed = GetRandomInt(1, udg_ICG_max)
else
set udg_ICG_seed = s
endif
endfunction
function ICG_Random takes nothing returns integer
set udg_ICG_seed = ICG_GetAdd(ICG_GetMult(ICG_GetInvert(udg_ICG_seed), udg_ICG_a), udg_ICG_b)
return udg_ICG_seed
endfunction
[/codes] |
评分
-
查看全部评分
|