program uniquerand32;
{$mode objfpc}
type
{ UniqueRandom32 }
UniqueRandom32 = class sealed
private
class var m_index:cardinal;
class var m_intermediateOffset:Cardinal;
class var Fseedbase,Fseedoffset:Cardinal;
class function permuteQPR(x:cardinal):cardinal;static;inline;
public
class constructor UniqueRandom32;
class function Next:Cardinal;inline;static;
end;
class function UniqueRandom32.permuteQPR(x: cardinal): cardinal;
const
prime:Cardinal = 4294967291;// closest prime to High(Cardinal);
Residue:Cardinal = 0;
begin
if x >= prime then
Result := x
else // The 5 integers out of range are mapped to themselves.
begin
residue := (qword(x) * x) mod prime;
if x <= (prime div 2) then
result:= residue
else
result := prime - residue;
end;
end;
class constructor UniqueRandom32.UniqueRandom32;
begin
FSeedBase :=RandSeed;
FSeedOffset := not Randseed;
m_index := permuteQPR(permuteQPR(FseedBase) + $682f0161);
m_intermediateOffset := permuteQPR(permuteQPR(FseedOffset) + $46790905);
end;
class function UniqueRandom32.Next: Cardinal;
begin
Result := permuteQPR((permuteQPR(m_index) + m_intermediateOffset) xor $5bf03635);
inc(m_index);
end;
{ demo }
var
i:integer;
begin
randseed := 5469; // must seed
//randomize; // or randomize
for i := 1 to 100 do
begin
write(UniqueRandom32.Next:20);
if i mod 5 = 0 then writeln;
end;
readln;
end.