samedi 9 mars 2019

Delphi implementation PCG32 PRNG

I wanted to try the PCG32 random number generator as a comparison with others, so did a quick and dirty conversion from the C code as a first test. I'm not a C programmer so I wanted to check the output stream from my conversion. Here is where I became unstuck, I can't find a source of info that gives both the seeds used and the resulting output. Here is my Q&D code:

unit pcg32;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  pcg32_state, pcg32_inc, J: UInt64;

implementation

{$R *.dfm}

function Quickanddirty(inc: UInt64): DWord;
var
  oldstate: UInt64;
  xsh, rot: Longword;

begin
  oldstate := pcg32_state;
  pcg32_state := oldstate * J + (inc or 1);
  xsh := ((oldstate shr 18) xor oldstate) shr 27;
  rot := oldstate shr 59;
  Result := (xsh shr rot) or (xsh shl ((NOT(rot) + 1) and 31));
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  f: Longword;
begin
  f := QuickandDirty(pcg32_inc);
  showmessage((Inttostr(f))+'  '+inttohex(f));
end;

INITIALIZATION
  J := 6364136223846793005;
  pcg32_state := $853c49e6748fea9b;// seed1
  pcg32_inc := $da3e39cb94b95bdb; // seed 2

end.

The seeds are those that seem to be quoted as the default values. The output of the first few numbers are:

355248013, 41705475, 3406281715, 4186697710, 483882979

(Compiled with Delphi 10.3). Can anyone point me to a source of info for comparison, or if they can compare this output from a known working version of pcg32? Maybe I'm just unlucky, but a trawl of the Internet turned up nothing of use.

For reference, the C code used was

typedef struct { uint64_t state;  uint64_t inc; } pcg32_random_t;

uint32_t pcg32_random_r(pcg32_random_t* rng)
{
    uint64_t oldstate = rng->state;
    // Advance internal state
    rng->state = oldstate * 6364136223846793005ULL + (rng->inc|1);
    // Calculate output function (XSH RR), uses old state for max ILP
    uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
    uint32_t rot = oldstate >> 59u;
    return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
}

Ted J




Aucun commentaire:

Enregistrer un commentaire