microbit: Minor optimisations to patch
- LFSR generated values in a subset of the range requested (rounded to the nearest lower power of 2). Corrected by increasing the number of bits usedby one, such that it now generated st least the power of 2 greater. - replaced enable/disable of interrupts with a local snapshot of randomValue. Much of the nordic software is sensitive to interrupt timings, so best avoided where possible. Chance of race condition is low, and effect is minimal (duplicate number returned).master
parent
958136673f
commit
f5cf8f2dd4
|
@ -315,30 +315,28 @@ int MicroBit::random(int max)
|
|||
do {
|
||||
m = (uint32_t)max;
|
||||
result = 0;
|
||||
while(m >>= 1) {
|
||||
do {
|
||||
// Cycle the LFSR (Linear Feedback Shift Register).
|
||||
// We use an optimal sequence with a period of 2^32-1, as defined by Bruce Schneider here (a true legend in the field!),
|
||||
// We use an optimal sequence with a period of 2^32-1, as defined by Bruce Schneier here (a true legend in the field!),
|
||||
// For those interested, it's documented in his paper:
|
||||
// "Pseudo-Random Sequence Generator for 32-Bit CPUs: A fast, machine-independent generator for 32-bit Microprocessors"
|
||||
// https://www.schneier.com/paper-pseudorandom-sequence.html
|
||||
// Avoid interupts (and hence fibre context switch) while we are doing this
|
||||
|
||||
__disable_irq();
|
||||
uint32_t rnd = randomValue;
|
||||
|
||||
randomValue = ((((randomValue >> 31)
|
||||
^ (randomValue >> 6)
|
||||
^ (randomValue >> 4)
|
||||
^ (randomValue >> 2)
|
||||
^ (randomValue >> 1)
|
||||
^ randomValue)
|
||||
rnd = ((((rnd >> 31)
|
||||
^ (rnd >> 6)
|
||||
^ (rnd >> 4)
|
||||
^ (rnd >> 2)
|
||||
^ (rnd >> 1)
|
||||
^ rnd)
|
||||
& 0x0000001)
|
||||
<< 31 )
|
||||
| (randomValue >> 1);
|
||||
| (rnd >> 1);
|
||||
|
||||
__enable_irq();
|
||||
randomValue = rnd;
|
||||
|
||||
result = ((result << 1) | (randomValue & 0x00000001));
|
||||
}
|
||||
result = ((result << 1) | (rnd & 0x00000001));
|
||||
} while(m >>= 1);
|
||||
} while (result > (uint32_t)max);
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue