Recent

Author Topic: Get random 32-bit (or 64-bit) numbers  (Read 7221 times)

Zoran

  • Hero Member
  • *****
  • Posts: 1829
    • http://wiki.lazarus.freepascal.org/User:Zoran
Get random 32-bit (or 64-bit) numbers
« on: April 04, 2017, 03:05:23 pm »
FPC has built-in pseudo-random number generator. There are (in System unit) three overloaded random functions exposed to public (as we can see here).

However, If I want to get pseudo-random Integer (32-bit sequence), I don't know how. The version of Random which returns integer takes a positive argument and returns a value between zero and this argument -- so the most I can get is 31-bit (if I pass MaxInt to the function).

Looking in sources, we can see that all these three functions internaly call function genrand_MT19937, which is not exposed to public (it is under implementation section of System unit).

If I understand well, this genrand_MT19937 function returns pseudo-random Longint. If I had access to this function, I could get pseudo-random 32-bit number. For 64-bit number I could use
Code: Pascal  [Select][+][-]
  1. (qword(cardinal(genrand_MT19937)) or ((qword(cardinal(genrand_MT19937)) shl 32)

Shouldn't we have access to this function? Seems to me that all three Random functions that we have exposed in system unit cut something from result of this original function.

Before I ask for this in bug tracker, I would like to discuss it here.

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Get random 32-bit (or 64-bit) numbers
« Reply #1 on: April 04, 2017, 03:57:32 pm »
FPC has built-in pseudo-random number generator. There are (in System unit) three overloaded random functions exposed to public (as we can see here).

However, If I want to get pseudo-random Integer (32-bit sequence), I don't know how. The version of Random which returns integer takes a positive argument and returns a value between zero and this argument -- so the most I can get is 31-bit (if I pass MaxInt to the function).

Looking in sources, we can see that all these three functions internaly call function genrand_MT19937, which is not exposed to public (it is under implementation section of System unit).

If I understand well, this genrand_MT19937 function returns pseudo-random Longint. If I had access to this function, I could get pseudo-random 32-bit number. For 64-bit number I could use
Code: Pascal  [Select][+][-]
  1. (qword(cardinal(genrand_MT19937)) or ((qword(cardinal(genrand_MT19937)) shl 32)

Shouldn't we have access to this function? Seems to me that all three Random functions that we have exposed in system unit cut something from result of this original function.

Before I ask for this in bug tracker, I would like to discuss it here.

The underlying algorithm has a 32 bit result on which all others are processed.
I published an FPC compatible unit here, look at the calculation in the TThreadSafeRandom.IM function. That is exacltly what you want. Or look up Marsaglia in the wiki for more 32 bit integer randoms.
See http://forum.lazarus.freepascal.org/index.php/topic,35050.msg242571.html#msg242571
See http://wiki.lazarus.freepascal.org/Marsaglia%27s_pseudo_random_number_generators
See https://en.wikipedia.org/wiki/Mersenne_Twister (for a direct answer).

All code written by me.

( I am still busy with true 64 bit, because it needs 128 bit expansion first, but I am almost finished with that.)

It may also show you that the 32 bit unsigned result is always there first (with any Prng) and the things we know as random are derived from that (in any language, btw)
The code on this forum is fully MT19937 compliant, like FPC's internal random. The code on the the FPC wiki for mersenne twister also contains proof against C/C++ version of MT19937. As it's all MT19937, of course you'll get the exact same results ;)


And.. Yes we should have access to the 32 bit unsigned result, but the internal calculation in FPC's random is slightly different from mine, so I don't know if that is possible.
Jonas knows that. But with my code, simply publish IM. I am not aware of any side effects.

« Last Edit: April 04, 2017, 05:40:40 pm by Thaddy »
Specialize a type, not a var.

Zoran

  • Hero Member
  • *****
  • Posts: 1829
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Get random 32-bit (or 64-bit) numbers
« Reply #2 on: April 05, 2017, 10:43:55 am »

Thank you, Thaddy.

Yes, your unit gives exactly what I asked for. Actually, I had already read your post and then I realized that built-in FPC functions cannot be used for so simple thing -- generating pseudo-random 32-bit value.

So, your post actually inspired me to ask this. Anyway, I think that FPC's genrand_MT19937 should be publicly accessible and I'm asking in bugtracker for this (here).

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Get random 32-bit (or 64-bit) numbers
« Reply #3 on: April 05, 2017, 11:10:15 am »
Zoran,

The whole of the 32 bits are used. To obtain a signed random it is sufficient to assign to a signed type ;)
That's the case with FPC's internal mt19937 and with my IM.

So part of your concern is already solved...
Specialize a type, not a var.

Zoran

  • Hero Member
  • *****
  • Posts: 1829
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Get random 32-bit (or 64-bit) numbers
« Reply #4 on: April 05, 2017, 11:55:25 am »
Zoran,

The whole of the 32 bits are used. To obtain a signed random it is sufficient to assign to a signed type ;)
That's the case with FPC's internal mt19937 and with my IM.

So part of your concern is already solved...

No, it is not solved with FPC's internal function.
Yes, it is the case with FPC's internal function, but the problem is it is not publicly accessible (it is not declared in interface section), so we cannot use it directly. And all random functions which we can use cut something from result.

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Get random 32-bit (or 64-bit) numbers
« Reply #5 on: April 05, 2017, 03:16:13 pm »
all random functions which we can use cut something from result.
That is normal. And according to specs. Signed is always 31 bits,unsigned is 32 bits. The intermediate (IM) gives the full 32 bit value for unsigned. That's logical since all operations are bitwise.
Specialize a type, not a var.

Zoran

  • Hero Member
  • *****
  • Posts: 1829
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Get random 32-bit (or 64-bit) numbers
« Reply #6 on: April 05, 2017, 05:12:38 pm »
all random functions which we can use cut something from result.
That is normal. And according to specs. Signed is always 31 bits,unsigned is 32 bits. The intermediate (IM) gives the full 32 bit value for unsigned. That's logical since all operations are bitwise.

I still don't understand, when there is fully functional routine that returns 32-bit result, why couldn't we use it?

Specifically, I need 64-bit unsigned random value. Now I can use something like this (it spares three elements from pseudo-random sequence):
Code: Pascal  [Select][+][-]
  1. function Random64Bit: QWord;
  2. begin
  3.   Result := Random(High(Int64)); // this calls genrand_MT19937 twice
  4.   if Random < 0.5 then // and this once more
  5.     Result := (QWord(1) shl 63) or Result;
  6. end;
  7.  

If I had access to genrand_MT19937, I would spare just two elements from pseudo-random sequence:
Code: Pascal  [Select][+][-]
  1. function Random64Bit: QWord;
  2. begin
  3.   Result := LongWord(genrand_MT19937);
  4.   Result := (Result shl 32) + LongWord(genrand_MT19937);
  5. end;
  6.  

So, Thaddy, don't you agree that the second way is better? Why do you think then that it is normal not to be able to use it?
How would you do it (of course, I mean without using your function, but just with what FPC offers you)?

Bart

  • Hero Member
  • *****
  • Posts: 5274
    • Bart en Mariska's Webstek
Re: Get random 32-bit (or 64-bit) numbers
« Reply #7 on: April 05, 2017, 06:12:41 pm »
function Random(U: UInt32): UInt32; (and likewise for UInt64) might be welcome addition to RTL?

Bart

Zoran

  • Hero Member
  • *****
  • Posts: 1829
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Get random 32-bit (or 64-bit) numbers
« Reply #8 on: April 05, 2017, 10:09:46 pm »
function Random(U: UInt32): UInt32; (and likewise for UInt64) might be welcome addition to RTL?

Bart

Exactly!
« Last Edit: April 05, 2017, 10:29:48 pm by Zoran »

Bart

  • Hero Member
  • *****
  • Posts: 5274
    • Bart en Mariska's Webstek
Re: Get random 32-bit (or 64-bit) numbers
« Reply #9 on: April 05, 2017, 11:06:48 pm »
Exactly!

File a feature request in the fpc bugtracker, and if possible, attach a patch.

Bart

Zoran

  • Hero Member
  • *****
  • Posts: 1829
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Get random 32-bit (or 64-bit) numbers
« Reply #10 on: April 06, 2017, 06:56:14 am »
Exactly!

File a feature request in the fpc bugtracker, and if possible, attach a patch.

Bart

I filed the bugreport, as I said already: http://bugs.freepascal.org/view.php?id=31633

 

TinyPortal © 2005-2018