Random: add yasmarang and cheap_rand generators.

main
Peter Hinch 2020-11-05 08:52:12 +00:00
rodzic 2e48324692
commit ee0d56bd7e
3 zmienionych plików z 70 dodań i 3 usunięć

Wyświetl plik

@ -32,7 +32,7 @@ and modules which are documented and supported.
4.5 [Timed function](./README.md#45-timed-function) Time execution with a decorator.
4.6 [ESP8266 MQTT benchmark](./README.md#46-esp8266-mqtt-benchmark) Test performance of MQTT with official library.
4.7 [Rotary incremental encoder](./README.md#47-rotary-incremental-encoder) Fast, simple, proven algorithm.
4.8 [A pseudo random number generator](./README.md#48-a-pseudo-random-number-generator)
4.8 [Pseudo random number generators](./README.md#48-pseudo-random-number-generators)
4.9 [Verifying incrementing sequences](./README.md#49-verifying-incrementing-sequences) Test communications drivers.
4.10 [Bitmaps](./README.md#410-bitmaps) Non-allocating ways to access bitmaps.
4.11 [Functors and singletons](./README.md#411-functors-and-singletons) Useful decorators.
@ -213,7 +213,7 @@ The [encoder_portable.py](./encoders/encoder_portable.py) version should work on
all MicroPython platforms. Tested on ESP8266. Note that interrupt latency on
the ESP8266 limits performance. ESP32 has similar limitations.
## 4.8 A pseudo random number generator
## 4.8 Pseudo random number generators
On the Pyboard V1.1, true random numbers may be generated rapidly with
`pyb.rng()` which uses a hardware random number generator on the
@ -226,7 +226,12 @@ number generator is seeded with an arbitrary initial value. On each call to the
function it will return a random number, but (given the same seed) the sequence
of numbers following initialisation will always be the same.
See [random.py](./random/random.py) for usage and timing documentation.
See [random.py](./random/random.py) for usage and timing documentation. The
[yasmarang generator](./random/yasmarang.py) is also included, along with my
own [cheap random](./random/cheap_rand.py). The latter constrains calculations
to 30 bits, allowing its use in an ISR. It comes with no guarantees of random
quality and the only statistical test is that the mean converges on the right
value.
## 4.9 Verifying incrementing sequences

Wyświetl plik

@ -0,0 +1,37 @@
# pseudorandom numbers for MicroPython. ISR friendly version.
# Probably poor quality numbers but useful in test scripts
# Author: Peter Hinch
# Copyright Peter Hinch 2020 Released under the MIT license
# Example usage to produce numbers between 0 and 99
# rand = cheap_rand(100)
# successive calls to rand() will produce the required result.
def cheap_rand(modulo, seed=0x3fba2):
x = seed
def func():
nonlocal x
x ^= (x & 0x1ffff) << 13;
x ^= x >> 17;
x ^= (x & 0x1ffffff) << 5;
return x % modulo
return func
# The sum total of my statistical testing
#import pyb, micropython, time
#rand = cheap_rand(1000)
#sum = 0
#cnt = 0
#def avg(n):
#global sum, cnt
#sum += n
#cnt += 1
#def cb(t):
#n = rand()
#micropython.schedule(avg, n)
#t = pyb.Timer(1, freq=20, callback=cb)
#while True:
#time.sleep(1)
#print(sum/cnt)

Wyświetl plik

@ -0,0 +1,25 @@
# yasmarang pseudorandom number generator.
# Source http://www.literatecode.com/yasmarang
# Author: Peter Hinch
# Copyright Peter Hinch 2020 Released under the MIT license
def yasmarang():
pad = 0xeda4baba
n = 69
d = 233
dat = 0
def func():
nonlocal pad, n, d, dat
pad = (pad + dat + d * n) & 0xffffffff
pad = ((pad<<3) + (pad>>29)) & 0xffffffff
n = pad | 2
d = (d ^ ((pad<<31) + (pad>>1))) & 0xffffffff
dat ^= ((pad & 0xff) ^ (d>>8) ^ 1) & 0xff
return (pad^(d<<5)^(pad>>18)^(dat<<1)) & 0xffffffff
return func
# Test: produces same outcome as website.
#ym = yasmarang()
#for _ in range(20):
#print(hex(ym()))