PCG Random Number Generator

Just a simple but efficient(I believe so) random number generator native extension using minimal C implementation of PCG.

Github: https://github.com/selimanac/defold-random

selimanac/defold-random - GitHub

It uses entropy seed internally. Tested on MacOS, iOS, Html5 and Windows(using Wine). It should work on Android and Linux too.

18 Likes

PCG is one of it not the best random number generation method available. Thank you for making this!

5 Likes

Is there any way of setting a static seed, so the same results are returned on any device? I’m using a Mersenne Twister Lua implementation for this now, but your library is 100x times faster.

It is not possible right now. But I think I can implemented it . I’m quite busy today, is it urgent?

2 Likes

That’s amazing! Not urgent at all, but it would be great to be able to use this super fast extension to map out my procedural universe!

2 Likes

Actually I’ve already implemented this for my small project. https://twitter.com/selimanac/status/1167796942128254976
But it is so messy. I have to make it more useful for everyone

Really nice! Just to confirm, using math.randomseed and math.random can produce inconsistent results across devices, right? As well as displaying less “random” random. :slight_smile:

I have no experience with math.randomseed and I’m not using math.random for a long time. I have no idea, sorry. I have a separate seed generator which uses entropy(if possible).

Tested it now. Setting a static math.randomseed and then running math.random gives completely different results in Defold IDE and an html export.

Edit: This only happens if large numbers are used (1000000+) as a seed. If it’s a float below 1 it seems to work. Doesn’t feel completely water tight…

2 Likes

Looking at the code, I’m trying to figure out how to do this. I suppose adding a new public method that takes a seed, then using that instead of time/entropy?

Yes it is. I already implemented it. I have to tested on different platforms first . I think, I’ll push it to the Git in a few hours.

Just updated the git repo: https://github.com/selimanac/defold-random
You can use rnd.seed(1593685104) for static seed.
Call rnd.seed() for using build-in entropy seed generator again.

I’ve tested on MacOS, iOS, Windows (using wine) and Html builds. Seems like it is working as expected. I’ll be glad if you can tested it too.

Example is here: https://github.com/selimanac/defold-random/blob/de856864790e74da03e8b20f4b68759b096a60bc/main/main.script#L51

:astonished:

I’ve tested it from the IDE and HTML5 and it works GREAT! Using rand resulted in visibly repetitive patterns, this is much more “random”.

ps. My seed was bigger than an unsigned 32 bits int, which breaks it, but that was easy to fix.

1 Like

It should be possible to use two 32 bit ints as a seed like a fake 64 bit. If this helps, I can implement it. like this: rnd.seed(num1, num2)

That would be a cool addition! Edit: @selimanac, that would be VERY cool. I just ran out of int space. :slight_smile:

Ok, I will.
I wondered; how did you manage to ran out of int space? :slight_smile: What are you trying to accomplish actually?

1 Like

I was hoping no one would ask! :slight_smile:

I’m creating a HUGE procedural universe. It’s divided in 10,000x10,000 tiles and each tile has a number of objects and sub-objects inside it. For each individual object to be unique, I need to seed the random generator with a concatenated coordinates of the tile and ids of all parents.

I nabbed the coord2index method here to convert coordinates to a unique number:

Because negative values are not allowed, I have to make sure each number is unique and bigger than 0, so even tile 0,0 is a fairly large number, and exponentially growing the further out from the centre you get.

By being able to use a second number to seed the random generator, I can concatenate the nested object IDs to get a truly unique seed for each object.

Phew. :sweat_smile:

And @selimanac THANKS for adding it!

Question: How would it work?

Would rnd.seed( 1,1 ) become a seed of 11, or 2? For it to work for me it’d have to be 11.

10000 * 10000 = 100000000, which isn’t close to half the range of a 32 bit integer.
So that range should suffice. Not sure why you need to salt the seed with “ids of all parents”?

To get a unique index into a tile: index = y * num_tiles_width + x
So tile (1,1) would become: 1 * 10000 + 1 = 10001

Also, I’m not an expert on seeds, but I imagine different rng’s behave better than others when the seed number is just a “running number” [0…100000000]. I would make sure the value became a bit more random, e.g. by multiplying it with a large prime.

In my mind, to make sure all objects are unique (to reduce the likelihood of two objects being exactly the same), I have to include the “breadcrumb” so each seed is unique.

Yes, and tile 10,000 x 10,000 would be something like 100010000. Concatenating the id of one object and sub object could result in 10001000012, which is too big. Addition doesn’t work because it would mean the seed is not unique.

Please, not MORE complexity! :smiley: In my tests the “randomness” of PCG is really, really good. Using math.random, for example, results in very visible repetitions. PCG appears butter smooth and unpredictable in comparison.