Skip to content

Commit 0788bbf

Browse files
Copilottwisti-dev
andcommitted
Fix biased binary search in RandomSelectorImpl.pick()
Co-authored-by: twisti-dev <[email protected]>
1 parent 53e237a commit 0788bbf

File tree

1 file changed

+14
-6
lines changed
  • surf-api-core/surf-api-core-api/src/main/kotlin/dev/slne/surf/surfapi/core/api/random

1 file changed

+14
-6
lines changed

surf-api-core/surf-api-core-api/src/main/kotlin/dev/slne/surf/surfapi/core/api/random/RandomSelectorImpl.kt

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,20 @@ internal class RandomSelectorImpl<E>(
1919

2020
override fun pick(randomGenerator: RandomGenerator): E {
2121
val totalWeight = cumulativeWeights.getDouble(cumulativeWeights.size - 1)
22-
val randomValue = randomGenerator.nextDouble(totalWeight)
23-
24-
val index = cumulativeWeights.binarySearch { if (it < randomValue) -1 else 0 }
25-
.let { if (it < 0) -(it + 1) else it }
26-
27-
return elements[index]
22+
val r = randomGenerator.nextDouble(totalWeight)
23+
24+
// lower_bound search for first cumulative >= r
25+
var lo = 0
26+
var hi = cumulativeWeights.size - 1
27+
while (lo < hi) {
28+
val mid = (lo + hi) ushr 1
29+
if (r <= cumulativeWeights.getDouble(mid)) {
30+
hi = mid
31+
} else {
32+
lo = mid + 1
33+
}
34+
}
35+
return elements[lo]
2836
}
2937

3038
override fun flow(randomGenerator: RandomGenerator): Flow<E> = kotlinx.coroutines.flow.flow {

0 commit comments

Comments
 (0)