Elementary cellular automaton/Random number generator: Difference between revisions

added assembler optimized pascal version
(added assembler optimized pascal version)
Line 305:
220 197 147 174 117 97 149 171 100 151
</pre>
 
=={{header|Pascal}}==
{{Works with|Free Pascal}}
Use 32-Bit assembler for speed.
<lang pascal>Program Rule30;
//http://en.wikipedia.org/wiki/Next_State_Rule_30;
//http://mathworld.wolfram.com/Rule30.html
//https://www.entwickler-ecke.de/viewtopic.php?t=111812
{$IFDEF FPC}
{$Mode Delphi}
{$ASMMODE INTEL}
{$OPTIMIZATION ON,ALL}
{$CODEALIGN proc=8}
{$ELSE}
{$APPTYPE CONSOLE}
{$ENDIF}
uses
SysUtils;
const
maxRounds = 100*1000*1000;
rounds = 10;
 
CpuF = 3.7e9; // AMD Ph XII 955 3.2 Ghz // Ryzen 5 1600 Turbo 3.7 Ghz
 
const
RULE30_BITSIZE = 64;
 
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 : tArr32;
 
procedure InitRule30_State;
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: Uint32): String;
var
i : integer;
begin
setlength(result,9);
result[1] :='_';
For i := 0 to 7 do
begin
result[7-i+2] := chr(Zahl AND 1+Ord('0'));
Zahl := Zahl shr 1;
end;
end;
 
procedure Ausgabe;
var
i : integer;
pArr08 :tpArr08;
begin
pArr08 := @Rule30_State[0];
For i := High(tLimit08)-1 Downto LOW(tLimit08) do
write(pArr08^[i]:4,BinStr(pArr08^[i]));
write('D',BinStr(pArr08^[High(tLimit08)-1]));
writeln;
end;
 
function dummy(a:pUint32):Uint32;assembler;
asm
 
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 // das 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 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;
var
i: integer;
T1,T0 : TDateTime;
Begin
writeln('Speedtest for statesize of ',RULE30_BITSIZE,' bits');
InitRule30_State;
T0 := time;
For i := 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);
Ausgabe;
T0 := time;
For i := maxRounds-1 downto 0 do
Next_State_Rule_30(@Rule30_State[0]);
T1 := time;
Ausgabe;
writeln(maxRounds,' calls take ',FormatDateTime('HH:NN:SS.zzz',T1-T0));
writeln('cycles per call : ',((T1-t0)*86400*CpuF)/maxRounds:0:2);
writeln;
end;
 
procedure Task;
var
k,j,b: integer;
Begin
writeln('The task ');
InitRule30_State;
For k := 1 to rounds do
Begin
b := 0;
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;
 
Begin
SpeedTest;
Task;
readln;
end.
</lang>
{{out}}
<pre>Speedtest for statesize of 64 bits
Dummy calls 00:00:00.140
cycles per call : 5.18
0_00000000 0_00000000 0_00000000 0_00000000 0_00000000 0_00000000 0_00000000 1_00000001D_00000000
247_11110111 53_00110101 233_11101001 101_01100101 155_10011011 150_10010110 206_11001110 177_10110001D_11110111
100000000 calls take 00:00:00.445
cycles per call : 16.46
 
The task
220 197 147 174 117 97 149 171 100 151</pre>
 
=={{header|Perl}}==
Anonymous user