Skip to content

feat(core): add gauss function to Random - #709

Merged
aarthificial merged 2 commits into
motion-canvas:mainfrom
ajs1998:random-gauss
May 23, 2023
Merged

feat(core): add gauss function to Random#709
aarthificial merged 2 commits into
motion-canvas:mainfrom
ajs1998:random-gauss

Conversation

@ajs1998

@ajs1998 ajs1998 commented May 23, 2023

Copy link
Copy Markdown
Contributor

gauss(mean, stdev) will return a normally distributed random value with a given mean and stdev.

The implementation was ported to TypeScript from Python's random.gauss(): https://docs.python.org/3/library/random.html#random.gauss

It includes a small optimization that caches a second independent random value
since the function always generates a pair.

Closes #704

`gauss(mean, stdev)`
will return a normally distributed random value with a given `mean`
and `stdev`.
The implementation was ported to TypeScript from Python's `random.gauss()`:
https://docs.python.org/3/library/random.html#random.gauss
It includes a small optimization
that caches a second independent random value
since the function always generates a pair.
@ajs1998
ajs1998 requested a review from aarthificial as a code owner May 23, 2023 01:59
Comment thread packages/core/src/scenes/Random.ts Outdated
Comment thread packages/core/src/scenes/Random.ts Outdated
Comment on lines +53 to +63
public gauss(mean = 0.0, stdev = 1.0): number {
let z = this.nextGauss;
this.nextGauss = null;
if (z === null) {
const x2pi = this.next() * 2 * Math.PI;
const g2rad = Math.sqrt(-2.0 * Math.log(1.0 - this.next()));
z = Math.cos(x2pi) * g2rad;
this.nextGauss = Math.sin(x2pi) * g2rad;
}
return mean + z * stdev;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference, this is Python's implementation:

def gauss(self, mu=0.0, sigma=1.0):
  random = self.random
  z = self.gauss_next
  self.gauss_next = None
  if z is None:
      x2pi = random() * TWOPI
      g2rad = _sqrt(-2.0 * _log(1.0 - random()))
      z = _cos(x2pi) * g2rad
      self.gauss_next = _sin(x2pi) * g2rad

  return mu + z * sigma

Comment thread packages/core/src/scenes/Random.ts Outdated
Comment thread packages/core/src/scenes/Random.ts Outdated
Comment thread packages/core/src/scenes/Random.ts Outdated
@ajs1998

ajs1998 commented May 23, 2023

Copy link
Copy Markdown
Contributor Author

The left is uniform distribution between 0-200

The right is gaussian distribution with a mean of 150 and standard deviation of 10

image

Here's another where the right has a mean of 150 and standard deviation of 50

image

I'm not experienced enough with Motion Canvas to make a histogram. I could probably do it though if you need further convincing that this works. Just eyeballing it I can see how the distribution isn't uniformly random, and my changes to the standard deviation match what I expect.

I also confirmed that the random values are reproducible just like the other methods in Random. Makes sense because I'm just using this.next() for random values.

@ajs1998
ajs1998 requested a review from aarthificial May 23, 2023 04:44
@aarthificial
aarthificial merged commit d7de3d5 into motion-canvas:main May 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for normally distributed random values

2 participants