{$mode objfpc}
{$asmmode intel}
{$OPTIMIZATION ON}
uses sysutils;
var T1: TDateTime;
function MWC: dword; inline;
var t : qword;
const c : dword = 100;
rngseed : dword = 100;
Multiplier : dword = 1791398085;
begin
t := qword (multiplier) * rngseed + c;
c := hi (t);
rngseed := lo(t);
result := lo(t);
end;
function MWC_ASM: dword; assembler; inline;
//FUNCTION AsmRand (rangw: dword): dword; pascal; assembler;
//returns integer 0..Range-1
{ High quality random numbers based on Multiply With Carry, by prof. Marsaglia
:: x(n)=a*x(n-1)+carry mod 2^32 ::
The period of the generator is a*2^31-1.
multiplier a can be selected from the following list (any one will do):
1791398085 1929682203 1683268614 1965537969 1675393560
1967773755 1517746329 1447497129 1655692410 1606218150
2051013963 1075433238 1557985959 1781943330 1893513180
1631296680 2131995753 2083801278 1873196400 1554115554}
const C : dword = 100;
RngSeed : dword = 100;
Multiplier : dword = 1791398085;
ASM
MOV EAX, rngseed
MUL Multiplier //64 bit multiplication, carry in EDX
ADD EAX, C //add previous carry
MOV RngSeed, EAX //update seed
MOV C, EDX //update carry, random number generation done
END;
const Num = 2000*100000;
var i,j: longint;
begin
writeln;
writeln ('Compare MWC : MWC_ASM');
for i := 1 to 10 do writeln (mwc:12,mwc_asm:12);
T1 := Now;
for i := num downto 0 do mwc;
writeln;
writeln ('------------- TIME MWC : ',(Now-T1)*3600*24*1e9/Num:3:3, ' ns. --------------------');
T1 := Now;
for j := num downto 0 do mwc_asm;
writeln;
writeln ('---------- TIME MWC_ASM : ',(Now-T1)*3600*24*1e9/Num:3:3, ' ns. --------------------');
end.