Elementary cellular automaton/Random number generator: Difference between revisions

m
→‎{{header|Pascal}}: Freepascal knows ROR and ROL using 64 Bit on 64-Bit Oprating system is fast
m (→‎{{header|Pascal}}: Freepascal knows ROR and ROL using 64 Bit on 64-Bit Oprating system is fast)
Line 308:
=={{header|Pascal}}==
{{Works with|Free Pascal}}
Fast only in 64 Bit.
Use 32-Bit assembler for speed like in Delphi-forum years ago.Sometimes it helps.<BR>Speedtest like in D [http://rosettacode.org/wiki/Elementary_cellular_automaton/Random_Number_Generator#D] with 8x2E6 calls.
 
<lang pascal>Program Rule30;
//https://www.entwickler-ecke.de/viewtopic.php?t=111812
//http://en.wikipedia.org/wiki/Next_State_Rule_30;
//http://mathworld.wolfram.com/Rule30.html
{$IFDEF FPC}
{$Mode Delphi}
{$ASMMODE INTEL}
{$OPTIMIZATION ON,ALL}
{$CODEALIGN proc=8}
Line 326 ⟶ 325:
maxRounds = 2*1000*1000;
rounds = 10;
CpuF = 3.7e9; // Ryzen 5 1600 Turbo 3.7 Ghz
 
CpuF = 3.7e9; // AMD Ph XII 955 3.2 Ghz // Ryzen 5 1600 Turbo 3.7 Ghz
 
const
RULE30_BITSIZE = 8*8;
 
SizeOfRegister = SizeOf(NativeUint);
BitsPerRegister = 8*SizeOfRegister;
 
Limit32Arr = RULE30_BITSIZE DIV BitsPerRegister -1;
Limit08Arr = RULE30_BITSIZE DIV 8 -1;
type
tLimit32 = 0..Limit32Arr+1;
tLimit08 = 0..Limit08Arr+1;
tArr32 = Array[tLimit32] OF Uint32;
tArr08 = Array[tLimit08] OF BYTE;
tpArr08 =^tArr08;
var
{$ALIGN 32}
Rule30_State : tArr32Uint64;
 
procedure InitRule30_State;inline;
var
i : integer;
begin
Rule30_State[Low(tArr32)]:= 1;
For i := Low(tArr32)+1 to High(tArr32) do
Rule30_State[i] := 0;
end;
 
function BinStr(Zahl: Uint32Uint64): String;
var
i : integer;
Line 371 ⟶ 351:
procedure Out_Rule30_State;
var
tmpState : Uint64;
i : integer;
tmp : array[0..7] of byte;
pArr08 :tpArr08;
begin
pArr08tmpState := @Rule30_State[0];
//SwapEndian(tmpState); //does not work
For i := High(tLimit08)-1 Downto LOW(tLimit08) do
For i := 0 to 7 do
write(pArr08^[i]:4,BinStr(pArr08^[i]));
Begin
write('D',BinStr(pArr08^[High(tLimit08)-1]));
tmp[i] := Byte(tmpState);
tmpState := tmpState SHR 8;
end;
For i := 7 downto 0 do
write(tmp[i]:4,BinStr(tmp[i]));
writeln;
end;
 
procedure Next_State_Rule_30;inline;
function dummy(a:pUint32):Uint32;assembler;
var
asm
run, prev,next: Uint64;
 
begin
run := Rule30_State;
Prev := RORQword(run,1);
next := ROLQword(run,1);
Rule30_State := (next OR run) XOR prev;
end;
 
function Next_State_Rule_30(a:pUint32):Uint32;assembler;
//EAX = a , EDX free to use
//EBX Rule30_State[0]
//ESI index 0..LimitArr-1
 
//EAX value
//ECX value one bit to the right
//EDX value one bit to the left
//EDI next value
asm
push EBX; push ESI;push EDI;
 
MOV EBX,EAX
MOV ESI,Limit32Arr*SizeOfRegister
ADD ESI,EBX
 
MOV ECX,Dword Ptr [ESI]; // the highest position into previous
MOV EAX,Dword Ptr [EBX]; // the lowest
MOV Dword Ptr [ESI+SizeOfRegister],EAX; // into one behind the end
 
@Loop:
MOV EDI,Dword Ptr [EBX+SizeOfRegister]; // the next
 
BT ECX,31 // MSB of prev
MOV ECX,EAX
RCL ECX,1 // shift MSB into LSB
 
BT EDI,0 // LSB of next
MOV EDX,EAX
RCR EDX,1 // shift LSB into MSB
 
OR EDX,EAX // POS[i] OR POS[i+1]
XOR ECX,EDX // POS[i] XOR (POS[i] OR POS[i+1])
MOV Dword Ptr [EBX],ECX; // save
ADD EBX,SizeOfRegister // next Pos
CMP EBX,ESI // MOV does not change flags
MOV ECX,EAX // running to previous
MOV EAX,EDI // next to running
JBE @Loop
 
POP EDI;POP ESI;POP EBX;
end;// ['EBX','ESI','EDI'];
 
procedure Speedtest;
Line 434 ⟶ 382:
i,j,b: NativeInt;
Begin
writeln('Speedtest for statesize of ',RULE30_BITSIZE64,' bits');
//Warm up start Turbo of CPU
For j := 10*1000*1000-1 downto 0 do
Next_State_Rule_30;
 
InitRule30_State;
T0 := time;
For i := 8*maxRounds-1 downto 0 do
dummy(@Rule30_State[0]);
T1 := time;
writeln('Dummy calls ',FormatDateTime('HH:NN:SS.zzz',T1-T0));
// Takte pro Durchlauf
writeln('cycles per call : ',((T1-t0)*86400*CpuF)/(maxRounds):0:2);
Out_Rule30_State;
T0 := time;
For i := maxRounds-1 downto 0 do
Line 450 ⟶ 394:
For j := 7 downto 0 do
Begin
b := (b+b) OR (Rule30_State[0] AND 1);
Next_State_Rule_30(@Rule30_State[0]);
end;
end;
Line 472 ⟶ 416:
For j := 7 downto 0 do
Begin
b := (b+b) OR (Rule30_State[0] AND 1);
Next_State_Rule_30(@Rule30_State[0]);
end;
write(b:4);
end;
writeln;
writeln;
end;
Line 484 ⟶ 427:
SpeedTest;
Task;
write(' <ENTER> ');readln;
end.</lang>
{{out}}
<pre>
//running compiled for 64-BIT
Speedtest for statesize of 64 bits
231_11100111 204_11001100 6_00000110 122_01111010 253_11111101 204_11001100 220_11011100 230_11100110
2000000 calls take 00:00:00.049
cycles per Byte : 90.65
The task
220 197 147 174 117 97 149 171 100 151
<ENTER>
 
//running compiled for 32-BIT
Speedtest for statesize of 64 bits
231_11100111 204_11001100 6_00000110 122_01111010 253_11111101 204_11001100 220_11011100 230_11100110
Dummy calls 00:00:00.031
2000000 calls take 00:00:00.109
cycles per call : 57.35
cycles per Byte : 201.65
0_00000000 0_00000000 0_00000000 0_00000000 0_00000000 0_00000000 0_00000000 1_00000001D_00000000
206_11001110 118_01110110 103_01100111 126_01111110 188_10111100 192_11000000 103_01100111 206_11001110D_11001110
2000000 calls take 00:00:00.069
cycles per Byte : 127.65
 
The task
220 197 147 174 117 97 149 171 100 151</pre>
<ENTER>
</pre>
 
=={{header|Perl}}==
Anonymous user