forked from KolibriOS/kolibrios
f119560b2d
git-svn-id: svn://kolibrios.org@6419 a494cfbc-eb01-0410-851d-a64ba20cac60
127 lines
3.3 KiB
PHP
127 lines
3.3 KiB
PHP
; ----------------------------- MOTHER.ASM -----------------------------
|
|
; Mother-of-All random number generator by Agner Fog 1998
|
|
; 32-bit mode version for 80x86 and compatible microprocessors
|
|
;
|
|
; MRandom returns a floating point number between 0 and 1.
|
|
; MRandomInit must be called before the first call to MRandom.
|
|
;
|
|
; C++ prototypes:
|
|
; extern "C" void MRandomInit (int seed);
|
|
; extern "C" double MRandom (void);
|
|
; extern "C" int MIRandom (int min, int max);
|
|
;
|
|
; © 1998, 2004 Agner Fog.
|
|
; GNU General Public License www.gnu.org/copyleft/gpl.html
|
|
; ----------------------------------------------------------------------
|
|
|
|
; The MRandom function is optimized for the Pentium microprocessor.
|
|
|
|
iglobal
|
|
mf3 dd 2111111111 ; factors
|
|
mf2 dd 1492
|
|
mf1 dd 1776
|
|
mf0 dd 5115
|
|
endg
|
|
|
|
|
|
uglobal
|
|
m0 dd ? ; history buffer
|
|
m1 dd ?
|
|
m2 dd ?
|
|
m3 dd ?
|
|
mc dd ?
|
|
temprng dq ? ; used for conversion to float
|
|
endg
|
|
|
|
|
|
proc init_random
|
|
|
|
mcall 26, 10 ; seed
|
|
xor ecx, ecx
|
|
; make random numbers and put them into buffer
|
|
@@:
|
|
imul eax, 29943829
|
|
dec eax
|
|
mov [m0+ecx*4], eax
|
|
inc ecx
|
|
cmp ecx, 5
|
|
jb @r
|
|
push edi
|
|
mov edi, 19
|
|
@@:
|
|
call MRandom
|
|
fstp st0
|
|
dec edi
|
|
jnz @r
|
|
pop edi
|
|
ret
|
|
|
|
endp
|
|
|
|
|
|
proc MRandom
|
|
|
|
call MBRandom ; random bits
|
|
mov edx, eax ; fast conversion to float
|
|
shr eax, 12
|
|
or eax, 3ff00000h
|
|
shl edx, 20
|
|
mov dword[temprng+4], eax
|
|
mov dword[temprng], edx
|
|
fld1
|
|
fld [temprng] ; partial memory stall here
|
|
fsubr st0, st1
|
|
ret
|
|
|
|
endp
|
|
|
|
|
|
proc MIRandom, max, min ; make random integer in desired interval
|
|
|
|
call MBRandom ; make random number
|
|
mov edx, [max]
|
|
mov ecx, [min]
|
|
sub edx, ecx
|
|
js .error ; max < min
|
|
inc edx ; max - min + 1
|
|
mul edx ; multiply random number by interval and truncate
|
|
lea eax, [edx+ecx] ; add min
|
|
ret
|
|
|
|
.error:
|
|
mov eax, 80000000h ; error exit
|
|
ret
|
|
|
|
endp
|
|
|
|
|
|
proc MBRandom
|
|
|
|
push edi
|
|
mov eax, [mf3]
|
|
mul [m3] ; x[n-4]
|
|
mov ecx, eax
|
|
mov eax, [m2] ; x[n-3]
|
|
mov edi, edx
|
|
mov [m3], eax
|
|
mul [mf2]
|
|
add ecx, eax
|
|
mov eax, [m1] ; x[n-2]
|
|
adc edi, edx
|
|
mov [m2], eax
|
|
mul [mf1]
|
|
add ecx, eax
|
|
mov eax, [m0] ; x[n-1]
|
|
adc edi, edx
|
|
mov [m1], eax
|
|
mul [mf0]
|
|
add eax, ecx
|
|
adc edx, edi
|
|
add eax, [mc]
|
|
adc edx, 0
|
|
mov [m0], eax
|
|
mov [mc], edx
|
|
pop edi
|
|
ret
|
|
|
|
endp |