Skip to content

Commit 2bc648c

Browse files
palimondostephentyrone
authored andcommitted
[stdlib] Lemire’s Nearly Divisionless Random Integer Generation (#25286)
* [stdlib] Lemire’s nearly divisionless random int Implementation of Daniel Lemire’s “Fast Random Integer Generation in Interval” See https://arxiv.org/pdf/1805.10941.pdf * [stdlib] Simpler, optimized expression * [stdlib] O'Neill’s modulo optimization See http://www.pcg-random.org/posts/bounded-rands.html#optimizing-modulo * [stdlib] Remove modulo optimization Swift, compared to C, seems unable to generate tightly fused instructions here for some reason (probably the division by zero check?)… removing. * [stdlib] Keep OpenBSD debiasing method on 32-bit systems until the https://bugs.swift.org/browse/SR-10910 is resolved. * [stdlib] TODO FIXME SR-10912 Remove the old OpenBSD generation method, once 32-bit systems support multipliedFullWidth on UInt64.
1 parent 77a6c9e commit 2bc648c

File tree

1 file changed

+14
-0
lines changed

1 file changed

+14
-0
lines changed

stdlib/public/core/Random.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ extension RandomNumberGenerator {
9494
upperBound: T
9595
) -> T {
9696
_precondition(upperBound != 0, "upperBound cannot be zero.")
97+
#if arch(i386) || arch(arm) // TODO(FIXME) SR-10912
9798
let tmp = (T.max % upperBound) + 1
9899
let range = tmp == upperBound ? 0 : tmp
99100
var random: T = 0
@@ -103,6 +104,19 @@ extension RandomNumberGenerator {
103104
} while random < range
104105

105106
return random % upperBound
107+
#endif
108+
#if arch(x86_64) || arch(arm64)
109+
var random: T = next()
110+
var m = random.multipliedFullWidth(by: upperBound)
111+
if m.low < upperBound {
112+
let t = (0 &- upperBound) % upperBound
113+
while m.low < t {
114+
random = next()
115+
m = random.multipliedFullWidth(by: upperBound)
116+
}
117+
}
118+
return m.high
119+
#endif
106120
}
107121
}
108122

0 commit comments

Comments
 (0)