Lazarus

Programming => General => Topic started by: ret on February 06, 2014, 05:25:39 pm

Title: internal random number generator lazarus vs. delphi
Post by: ret on February 06, 2014, 05:25:39 pm
Hi,

I am trying to port a delphi application to lazarus. While porting I discovered differences with the internal random number generator between lazarus an delphi. The application need to generate random numbers which need to be identic for the same initialisation values. (for compatibility reasons within both lazarus and delphi application).

for example
Code: [Select]
for i:= 1 to 10 do begin
  RandSeed := userId + i * 31337; 
  digit := Random(10);
end;

These produce different output in delphi an lazarus.

Any help in emulating the delphi random number generator's behavior whith lazarus is much appreciated.

ret
Title: Re: internal random number generator lazarus vs. delphi
Post by: marcov on February 06, 2014, 05:32:58 pm
Usually in such cases, people package and use a 3rd party random generator. (since the Delphi RG might also change with versions).
Title: Re: internal random number generator lazarus vs. delphi
Post by: ret on February 06, 2014, 05:38:34 pm
Thanks for your reply.
Is there any detailed information how delphi RG's numbers are generated?
I think the simplest solution to my problem would be to recreate the behavior of the delphi's RG in lazarus.
Title: Re: internal random number generator lazarus vs. delphi
Post by: marcov on February 06, 2014, 05:48:46 pm
Is there any detailed information how delphi RG's numbers are generated?
I think the simplest solution to my problem would be to recreate the behavior of the delphi's RG in lazarus.

Probably the only way to find out is study the Delphi source, but that is copyrighted code.
Title: Re: internal random number generator lazarus vs. delphi
Post by: ret on February 06, 2014, 05:55:45 pm
Thank you. I'll have a look in to that.

Unfortunatly I don't have the delphi IDE to my handy. That's why we are going to port the applications source code to lazarus.
Title: Re: internal random number generator lazarus vs. delphi
Post by: User137 on February 06, 2014, 09:16:50 pm
You could make a dll in Delphi that calls random(), then use that random through a dll function in Lazarus.
Title: Re: internal random number generator lazarus vs. delphi
Post by: TurboRascal on February 07, 2014, 06:00:48 am
Reliance on a RTL included random number generator with unknown algorithm is a poor choice. Since it is meant ot give... er... random numbers, and as mentioned it can (and really should) change with every different RTL. It is not meant to be used that way.

You should create your own pseudorandom number generator for this purpos. You might use a mix of hash algorithms on your initial data and seed, for example.
Title: Re: internal random number generator lazarus vs. delphi
Post by: marcov on February 07, 2014, 09:13:48 am
I think user137's idea is the best.
Title: Re: internal random number generator lazarus vs. delphi
Post by: taazz on February 07, 2014, 09:38:57 am
I think that if he has access to delphi then copying the code verbatim and using it with FPC is the best there is nothing to prevent him (assuming he has a legal license of delphi) from reusing the code in there as he wants to.
Title: Re: internal random number generator lazarus vs. delphi
Post by: BrunoK on February 07, 2014, 01:05:34 pm
If you don’t really need "Delphi's specific" random generator, port the FPC random generator in a custom unit and use it with either Lazarus or Delphi.

Extract the random generator of Fpc  (unit \fpc\fpcsrc\rtl\inc\systemh.inc and \fpc\fpcsrc\rtl\inc\systemh.inc)
 
Rename public bits and pieces to something different than existing code.

That should work.
Title: Re: internal random number generator lazarus vs. delphi
Post by: ret on February 07, 2014, 06:29:43 pm
Unfortunatley, I have to exactly clone the behaviour of delphi's prng for my use case.

One aproach was following suggestion of putting the random function into a dll.

But after some research it turned out that delphi is using a linear congruential generator (see http://en.wikipedia.org/wiki/Linear_congruential_generator).  The equation for generating the number sequence is: x_{n+1}=(a*x_n + c) mod m

Further investigation depicted delphi is using the following values for the constants:
a=134775813
c=1
m=2^32

After a while of fiddling around I ended up with this piece of code, which is exactly reproducung the delphi's random number squence.

Code: [Select]
function hr_random2(const pi_Max: Integer):Integer;
var
  Temp: Longint;
begin
  Temp := 134775813 * i_hr_RandomSeed + 1;
  i_hr_RandomSeed := Temp; //
  Result := (UInt64(Cardinal(pi_Max)) * UInt64(Cardinal(Temp))) shr 32;
end;

Thanks to all who pointed me into the right direction.