processing / p5.js

p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the core principles of Processing. http://twitter.com/p5xjs —
http://p5js.org/
GNU Lesser General Public License v2.1
21.1k stars 3.22k forks source link

[p5.js 2.0 RFC Proposal]: RNG algorithm change #7017

Open limzykenneth opened 1 month ago

limzykenneth commented 1 month ago

Increasing access

xorshift128+ have a better overall randomness and speed as compared to the currently used LCG, although the speed aspect has been mostly observed in RNG implemented in other languages so it is harder to determine how well it will translate to JavaScript. This change can help avoid some of the potential pitfalls with LCG that some users has observed before.

Which types of changes would be made?

Most appropriate sub-area of p5.js?

What's the problem?

There is not a significant problem to solve with this proposal, the main aim is to use the same RNG algorithm as the browser's own Math.random() implementation.

What's the solution?

Seeded random number generator (RNG) will use xorshift128+. The current algorithm for RNG used in p5.js is an version of a Linear Congruential Generator (LCG).

The main reasoning for this change is for performance. xorshift128+ performs better than LCG and it is the internal implementation of most of the current major browsers for Math.random(). The random property of xorshift128+ is similar if not better than LCG.

This will be a breaking change as existing seeded RNG will not give the same random number sequence once the algoritm has switched to use xorshift128+. Consideration can be made to create a compatibility addon library that patch seeded RNG to use the old LCG RNG if necessary.

Example implementation of a xorshift128+ backed RNG with compatible API to p5.js can be found here.

Pros (updated based on community comments)

Cons (updated based on community comments)

This is a fairly minor change although still in effect a breaking change since it will change the sequence of numbers returned by a seeded random number generator as well as seeded noise. This will only affect seeded RNG, unseeded ones uses Math.random() which is not seeded.

Proposal status

Under review

mattdesl commented 1 month ago

Another implementation (much smaller and perhaps faster), MIT license. https://gist.github.com/mattdesl/43893dec295d4d2cba75438c0027830a

I think a change to PRNG should ideally be considered with how the seed is set as well. In my case I chose djb2 to hash the seed string into 128 bits. For some projects I have even exposed the raw 128 bit seed getter/setter to my gen art programs, for example when I want to encode the random state in as few bits as possible into a file.

limzykenneth commented 1 month ago

@mattdesl Thanks for sharing. The current implementation of randomSeed() only accepts a number, I can see hashing can be a good way to enable string to be used as seed as well.